Data Structure of the Periodic Table of Elements

后端 未结 2 767
囚心锁ツ
囚心锁ツ 2021-01-16 09: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 c

2条回答
  •  半阙折子戏
    2021-01-16 09:39

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

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

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

提交回复
热议问题