Data Structure of the Periodic Table of Elements

Deadly 提交于 2019-12-01 11:55:16

问题


My goal is to use the periodic table of elements (or a list) to get information about a specific element in Java. I want to search it by atomic number and symbol (but that conversion should be simple).

I found that information in this JQuery plugin. But it is stored as a JSON file.

It seems like it would be most efficient to hardcode the information (since it doesn't change too often and due to performance reasons), but how do I convert JSON to a hardcoded enum?


回答1:


Since:

  • the information about elements is totally static
  • each elemental symbol is alphanumeric
  • the discovery of new elements is both rare and irrelevant (because they are extremely unstable)

An enum seems a good option:

public enum Element {
    H(1, "Hydrogen", 1.008, -259.1),
    He(2, "Helium", 4.003, -272.2),
    Li(3, "Lithium", 6.941, 180.5),
    // ... 90+ others
    ;

    private static class Holder {
        static Map<Integer, Element> map = new HashMap<Integer, Element>();
    }

    private final int atomicNumber;
    private final String fullName;
    private final double atomicMass;
    private final double meltingPoint;

    private Element(int atomicNumber, String fullName, double atomicMass, double meltingPoint) {
        this.atomicNumber = atomicNumber;
        this.fullName = fullName;
        this.atomicMass = atomicMass;
        this.meltingPoint = meltingPoint;
        Holder.map.put(atomicNumber, this);
    }

    public static Element forAtomicNumber(int atomicNumber) {
        return Holder.map.get(atomicNumber);
    }

    public int getAtomicNumber() {
        return atomicNumber;
    }

    public String getFullName() {
        return fullName;
    }

    public double getAtomicMass() {
        return atomicMass;
    }

    public double getMeltingPoint() {
        return meltingPoint;
    }
}

There's a bit of java kung fu going on here that deserves an explanation. The map is put inside a static inner (holder) class so it gets initialized before the enum instances are initialized, that way they can add themselves to it. If not in the inner static class, it would not be initialize, because the first thing initialized in the enum class must be the instances, but static inner classes are initialized before the class is initialized.

This approach means the the instances don't need to be listed in any particular order (they could be alphabetical listed, or otherwise).




回答2:


Suppose you have a PeriodicTable.txt file with following format:

ATOMIC_NUMBER SYMBOL OTHER_INFO

Like:

1 H Hydrogen -> Lightest element
2 He Helium -> Second lightest element
3 Li Lithium -> Third lightest element
// and so on...

Then you can have a fairly straightforward implementation of your own PeriodicTable like following:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class PeriodicTable
{
  private List<Element> elements;

  public PeriodicTable() throws IOException
  {
    elements = new ArrayList<>();
    List<String> list = Files.readAllLines(Paths.get("PeriodicTable.txt"));
    list.forEach(this::process);
  }

  public static void main(String[] args) throws IOException
  {
    final PeriodicTable periodicTable = new PeriodicTable();

    System.out.println(periodicTable.getElementByNumber(1));
    System.out.println(periodicTable.getElementBySymbol("Li"));
  }

  private void process(String line)
  {
    try (Scanner scanner = new Scanner(line))
    {
      int atomicNumber = scanner.nextInt();
      String symbol = scanner.next();
      String info = scanner.nextLine();

      elements.add(new Element(atomicNumber, symbol, info));
    }
  }

  public Element getElementByNumber(int atomicNumber)
  {
    return elements.stream().
      filter(e -> e.atomicNumber == atomicNumber).
      findFirst().orElse(null);
  }

  public Element getElementBySymbol(String symbol)
  {
    return elements.stream().
      filter(e -> e.symbol.equals(symbol)).
      findFirst().orElse(null);
  }

  private class Element
  {
    private String info;
    private int atomicNumber;
    private String symbol;

    public Element(int atomicNumber, String symbol, String info)
    {
      this.atomicNumber = atomicNumber;
      this.symbol = symbol;
      this.info = info;
    }

    public String toString()
    {
      return "[ " + atomicNumber + " " + symbol + " " + info + " ]";
    }
  }
}

If you see, I have created an Element class which holds the atomic number, symbol, and info of the element, and I have a list of elements in PeriodicTable class.

I read the PeriodicTable data from the PeriodicTable.txt file and process each line of the text file by parsing it appropriately and creating element for each line and adding it to the elements.

I also add two methods for filtering the element based on atomic number and symbol properties.

The code works in Java 8, so you should have at least that to run it, or one can easily write a code for this which will run on earlier JVMs, though it won't be as compact as this one.

Since there are just limited number of elements in the PeriodicTable, I don't bother to have elements sorted by their atomic number though they will be if your PeriodicTable.txt file has elements with increasing atomic number.

Since we know the exact number of elements in the PeriodicTable and its something that doesn't change frequently, the filtering methods take constant time.

All you have to do now is create a proper PeriodicTable.txt file which can then be used by the program.

Note: The PeriodicTable class can be written in better ways as well. This is just an example. I can have it as Singleton. I can even have enum of Element with hardcoded values, but I think loading data from file will keep the code cleaner.

One can even augment the PeriodicTable class with additional properties to each Element, by changing the process() method accordingly, and changing the format of the text file based on the assumptions, and augmenting the Element class, so that it can hold even more information.

Just for fun, following is a Singleton based solution:

// PeriodicTable.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class PeriodicTable
{
  private static PeriodicTable periodicTable = new PeriodicTable();
  private List<Element> elements;

  private PeriodicTable()
  {
    try
    {
      elements = new ArrayList<>();
      List<String> list = Files.readAllLines(Paths.get("PeriodicTable.txt"));
      list.forEach(this::process);
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  public static Element getElementByNumber(int atomicNumber)
  {
    return periodicTable.elements.stream().
      filter(e -> e.atomicNumber == atomicNumber).
      findFirst().orElse(null);
  }

  public static Element getElementBySymbol(String symbol)
  {
    return periodicTable.elements.stream().
      filter(e -> e.symbol.equals(symbol)).
      findFirst().orElse(null);
  }

  private void process(String line)
  {
    try (Scanner scanner = new Scanner(line))
    {
      int atomicNumber = scanner.nextInt();
      String symbol = scanner.next();
      String info = scanner.nextLine();

      elements.add(new Element(atomicNumber, symbol, info));
    }
  }

  private class Element
  {
    private String info;
    private int atomicNumber;
    private String symbol;

    public Element(int atomicNumber, String symbol, String info)
    {
      this.atomicNumber = atomicNumber;
      this.symbol = symbol;
      this.info = info;
    }

    public String toString()
    {
      return "[ " + atomicNumber + " " + symbol + " " + info + " ]";
    }
  }
}

// Demo.java
public class Demo
{
  public static void main(String[] args)
  {
    System.out.println(PeriodicTable.getElementByNumber(1));
    System.out.println(PeriodicTable.getElementBySymbol("Li"));
  }
}

Now you can use your PeriodicTable safely and directly as shown in the Demo method.



来源:https://stackoverflow.com/questions/22738023/data-structure-of-the-periodic-table-of-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!