[英]Data Structure of the Periodic Table of Elements
我的目标是使用元素周期表(或列表)来获取有关Java中特定元素的信息。 我想按原子序号和符号搜索它(但是转换应该很简单)。
我在此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<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功夫值得解释。 映射被放置在静态内部(所有者)类中,因此在初始化枚举实例之前对其进行了初始化,这样它们便可以将自身添加到其中。 如果不在内部静态类中,则不会进行初始化,因为在枚举类中初始化的第一件事必须是实例,但是静态内部类在初始化类之前已初始化。
这种方法意味着实例不需要以任何特定顺序列出(它们可以按字母顺序列出,或以其他方式列出)。
假设您有一个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
类,其中包含该Element
的atomic number
, symbol
和info
,并且在PeriodicTable
类中有一个elements
列表。
我从PeriodicTable.txt
文件中读取了PeriodicTable
数据,并通过适当地解析文本文件并为每一行创建元素并将其添加到elements
来处理文本文件的每一行。
我还添加了两种基于atomic number
和symbol
属性过滤元素的方法。
该代码可在Java 8中运行,因此您至少应具有运行该代码的权限,或者可以轻松地为此代码编写将在早期JVM上运行的代码,尽管它不会像此版本那么紧凑。
由于PeriodicTable中元素的数量有限,因此,如果您的PeriodicTable.txt
文件中包含原子序数增加的元素,它们将按照atomic number
排序,尽管我会费心。
由于我们知道PeriodicTable
中元素的确切数目及其不经常更改的内容,因此过滤方法花费的时间是恒定的。
现在,您要做的就是创建一个正确的PeriodicTable.txt
文件,程序可以使用该文件。
注意: PeriodicTable
类也可以用更好的方式编写。 这只是一个例子。 我可以将其作为Singleton。 我什至可以使用具有硬编码值的Element
enum
,但是我认为从文件加载数据将使代码更整洁。
通过相应地更改process()
方法,并根据假设更改文本文件的格式,并扩展Element
类,甚至可以为每个Element增加对PeriodicTable
类的附加属性,从而可以容纳更多信息。
只是为了好玩,以下是基于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<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"));
}
}
现在,您可以安全地,直接地使用您的PeriodicTable
,如Demo
方法所示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.