元素周期表的数据结构

时间:2014-03-29 22:59:05

标签: java enums cheminformatics

我的目标是使用元素周期表(或列表)来获取有关Java中特定元素的信息。我想通过原子序数和符号进行搜索(但转换应该很简单)。

我在this JQuery plugin中找到了这些信息。但它存储为JSON文件。

似乎最有效的是对信息进行硬编码(因为它不会经常更改并且由于性能原因),但是如何将JSON转换为硬编码的enum

2 个答案:

答案 0 :(得分:6)

自:

  • 关于元素的信息是完全静态的
  • 每个元素符号是字母数字
  • 新元素的发现既罕见又不相关(因为它们非常不稳定)

枚举似乎是个不错的选择:

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;
    }
}

这里有一些java功夫,值得一解。该映射放在一个静态内部(holder)类中,因此在初始化枚举实例之前初始化,这样他们就可以将它们添加到它中。如果不在内部静态类中,则不会初始化,因为在枚举类中初始化的第一件事必须是实例,但是静态内部类在之前初始化 class已初始化。

这种方法意味着不需要按任何特定顺序列出实例(它们可以按字母顺序列出,或者以其他方式列出)。

答案 1 :(得分:2)

假设您有一个PeriodicTable.txt文件,格式如下:

ATOMIC_NUMBER SYMBOL OTHER_INFO

像:

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

然后,你可以像下面这样简单地实现自己的PeriodicTable

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 + " ]";
    }
  }
}

如果你看到,我创建了一个Element类,其中包含该元素的atomic numbersymbolinfo,并且我有一个{{1}列表在elements类中的1}}。

我从PeriodicTable文件中读取PeriodicTable数据,并通过适当地解析文本文件的每一行并为每一行创建元素并将其添加到PeriodicTable.txt来处理该文本文件的每一行。

我还添加了两种基于elementsatomic number属性过滤元素的方法。

代码在Java 8中运行,所以你至少应该运行它,或者你可以轻松编写一个代码来运行在早期的JVM上,尽管它不会像这个一样紧凑。 。

由于PeriodicTable中的元素数量有限,我不必费心按symbol排序元素,尽管如果你的atomic number文件包含增加原子的元素,它们就会出现数。

由于我们知道PeriodicTable.txt中元素的确切数量及其不经常变化的元素,因此过滤方法需要一段时间。

现在你要做的就是创建一个合适的PeriodicTable文件,然后程序可以使用它。

注意:PeriodicTable.txt类也可以用更好的方式编写。这只是一个例子。我可以把它当作Singleton。我甚至可以PeriodicTable enum使用硬编码值,但我认为从文件加载数据会使代码更清晰。

甚至可以通过相应地更改Element方法,并根据假设更改文本文件的格式,以及增加{{{}来扩充PeriodicTable类,并为每个元素添加其他属性。 1}}类,以便它可以保存更多信息。

为了好玩,以下是基于单身人士的解决方案:

process()

现在,您可以安全直接地使用Element,如// 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")); } } 方法所示。