元素周期表的数据结构

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

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

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

以来:

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

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

 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 map = new HashMap(); } 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)类中,因此它在枚举实例初始化之前被初始化,这样他们就可以将它们添加到它中。 如果不在内部静态类中,则不会初始化,因为在枚举类中初始化的第一件事必须是实例,但是在初始化类之前初始化静态内部类。

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

假设您有一个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 elements; public PeriodicTable() throws IOException { elements = new ArrayList<>(); List 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类,它保存了Elementatomic numbersymbolinfo ,我在PeriodicTable类中有一个elements列表。

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

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

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

由于PeriodicTable中只有有限数量的元素,我不打算按atomic number排序元素,尽管如果你的PeriodicTable.txt文件中的元素具有增加的primefaces序数,它们就是这样。

由于我们知道PeriodicTable中元素的确切数量及其不经常更改的内容,因此过滤方法需要恒定的时间。

您现在要做的就是创建一个适当的PeriodicTable.txt文件,然后该程序可以使用该文件。

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

甚至可以通过相应地更改process()方法,并根据假设更改文本文件的格式,以及扩充Element类来扩充PeriodicTable类以及每个Element的附加属性,以便它可以保存更多信息。

只是为了好玩,以下是基于Singleton的解决方案:

 // 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 elements; private PeriodicTable() { try { elements = new ArrayList<>(); List 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")); } } 

现在,您可以安全直接地使用PeriodicTable ,如Demo方法中所示。

Interesting Posts