1

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

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

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

4

2 回答 2

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 功夫,值得解释。该映射被放置在一个静态内部(持有人)类中,因此它在枚举实例初始化之前被初始化,这样他们就可以将自己添加到其中。如果不在内部静态类中,则不会被初始化,因为在枚举类中初始化的第一件事必须是实例,但静态内部类在类初始化之前被初始化。

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

于 2014-03-30T00:10:30.430 回答
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元素的类,并且我有一个类elements中的列表PeriodicTable

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

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

该代码在 Java 8 中工作,因此您至少应该有运行它,或者可以很容易地为此编写代码,该代码将在早期的 JVM 上运行,尽管它不会像这个那么紧凑。

由于元素周期表中的元素数量有限,因此我不会费心将元素按它们排序,atomic number尽管如果您的PeriodicTable.txt文件中的元素原子序数增加,它们就会排序。

由于我们知道元素的确切数量PeriodicTable以及它不会经常变化的东西,因此过滤方法需要恒定的时间。

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

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

甚至可以通过相应地更改方法,并根据假设更改文本文件的格式,并扩充类,从而PeriodicTable为每个元素增加额外的属性,以便它可以包含更多信息。 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"));
  }
}

现在您可以PeriodicTable按照方法所示安全直接地使用您的了Demo

于 2014-03-29T23:46:32.750 回答