Data Structure of the Periodic Table of Elements - java

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 conversion should be simple).
I found that information in this JQuery plugin. But it is stored as a JSON file.
It seems like it would be most efficient to hardcode the information (since it doesn't change too often and due to performance reasons), but how do I convert JSON to a hardcoded enum?

Since:
the information about elements is totally static
each elemental symbol is alphanumeric
the discovery of new elements is both rare and irrelevant (because they are extremely unstable)
An enum seems a good option:
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;
}
}
There's a bit of java kung fu going on here that deserves an explanation. The map is put inside a static inner (holder) class so it gets initialized before the enum instances are initialized, that way they can add themselves to it. If not in the inner static class, it would not be initialize, because the first thing initialized in the enum class must be the instances, but static inner classes are initialized before the class is initialized.
This approach means the the instances don't need to be listed in any particular order (they could be alphabetical listed, or otherwise).

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<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 + " ]";
}
}
}
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<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"));
}
}
Now you can use your PeriodicTable safely and directly as shown in the Demo method.

Related

adding into an Array list of objects from a text file in java

i thinkj i have a type argument problem which im really confused about, Ive started with an Arraylist which, extends to the another class with my main methods. and i have a Events class, which i want to categorize from the txt file, the main problem i have is adding from my txt file which iread into an ArrayList, java pops up with this error message
incompatible types: java.lang.String cannot be converted to CSC8012.Events
But in my events it has String? Im really confused
This is my generic arraylist i think?
import java.util.ArrayList;
public class SortedArrayList<E extends Comparable> extends
ArrayList<E> {
public void insert(E e) {
this.add(e);
int lastIndex = 0;
for( lastIndex = this.size() -1 ; lastIndex > 0 && this.get(lastIndex-1).compareTo(e) > 0 ; lastIndex--){
this.set(lastIndex, this.get(lastIndex-1));
}
this.set(lastIndex,e);
}
}
Heres my events class objects
public class Events implements Comparable<Events>{
//fields setting up the variables
String ticketsbought;
String eventname;
public Events(String ticketsbought, String eventname ){
this.ticketsbought = ticketsbought;
this.eventname = eventname;
}
#Override
public int compareTo (Events E){
return
ticketsbought.compareTo(E.getTicketsbought()) + eventname.compareTo(E.getEventname());
}
public String getTicketsbought() {
return ticketsbought;
}
public String getEventname() {
return eventname;
}
//setting it up for the main method from the constructor fields above
public void setTicketsbought(String ticketsbought) {
this.ticketsbought = ticketsbought;
}
public void setEventname(String eventname) {
this.eventname = eventname;
}
#Override
public String toString()
{
return "Tickets bought " + this.ticketsbought + "Event name " + this.eventname;
}
}
My main menu class
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Objects;
import java.util.ArrayList;
import java.util.Collections;
java.util.Scanner;
public class MainProgram extends SortedArrayList{
public static void main(String[] args) throws FileNotFoundException{
boolean bye = false;
String line;
String option;
Scanner sc = new Scanner(System.in); //tos take in our input
do{
System.out.println("Choose an option.."); // heres our options
System.out.println("e Information on all events");
System.out.println("c All information on clients");
System.out.println("f to quit");
System.out.println("b to update when tickets are bought by a registered Client");
System.out.println("r to update the stored data when a Client cancels a ticket");
option = sc.nextLine();
switch (option) { // these are splitting our inputs to these cases with different outcomes
case "e":
//System.out.println("information on events");
Scanner inFile = new Scanner(new FileReader("input.txt"));
// Other declarations// Reading and processing the input data// Printing out the results outFile.close();
ArrayList<Events> events = new ArrayList<>();
while(inFile.hasNextLine()) {
String data = inFile.next();
events.add(data);//error based on these? Event is based off of arraylist<E> and inherits from those whilst i have them as string?
You are seeing the exception because of Generics in Java.
Your ArrayList is declared to take Events objects.
ArrayList<Events> events = new ArrayList<>();
However, you are trying to add a String object to it.
String data = inFile.next();
events.add(data); //Cannot add a String object, only Events object allowed.
One way to fix this is to create an Events object using the String, and then add to the Arraylist. I am assuming each line has Event name and String in it, separated by a comma.
//Get your event name and tickets from the String data.
String tokens[] = data.split(",");
String eventName = tokens[0];
String ticketsBought = tokens[1];
//create an events object
Events eventObj = new Events(eventName, ticketsBought);
//Now add to your arraylist.
events.add(eventObj);
As an aside, you do not need to extend SortedArrayList in MainProgram. The main class is usually top level class in your project, and it will only contain objects (this is a common practice). If you want to use the new logic you have added in SortedArrayList, then instead of creating ArrayList<Events> events = new ArrayList<>();, you can create SortedArrayList<Events> events = new SortedArrayList<>();

Issue with referncing objects that do not have a name

I´m new to programming and I have this task to implement a simple booking System for bus tickets.
We´re supposed to implement a method that adds new bus routes using the attributes: busNumber, start, destination, price, currency. To save the bus routes I´m using an arraylist and save new objects like this:
Booking.add(new Booking(1, "France", "Latvia", 2.05, Currency.EUR))
My issue now is working with those objects since they don´t have a name. I don't know the exact number of objects, so I have to do it this way (i think so at least). Where the issue occurred is at the method "remove", that is supposed to remove a bus route. I thought I could use an Iterator to iterate through the ArrayList and compare the busNumbers but it´s not working.
Another issue I have is, that when I want to print all the objects in my Array list it just prints the last object as many times as there are objects in my ArrayList. Also, my method and attributes are all static now otherwise I wouldn´t know how to use them in another class.
Does anybody has some advice for a newbie please?
My Code is below:
import java.util.ArrayList;
import java.util.Iterator;
public class Booking {
static int busNumber;
static int customerID = 1; //First customerID starts with 1
static String name;
static double price;
static int invoiceNumber = 1; //First invoicenumber starts with 1.
static String start;
static String destination;
static Currency currency;
static ArrayList<Booking> bookable = new ArrayList<Booking>();
//Constructor
public Booking(int busNumber, String start, String destination, double price, Currency currency) {
this.busNumber = busNumber;
this.start = start;
this.destination = destination;
this.price = price;
this.currency = currency;
}
public int getBusNumber() {
return busNumber;
}
public static void add(Booking add) { // add-method. Adds the bus routes to the booking system
bookable.add(add);
}
public static void remove(int busNumber) { // Here´s one of my issues. That´s what i have.
Iterator<Booking> it = bookable.iterator();
if ( == busNumber) {
bookable.remove(it);
}
}
public static void listRoute() {
for (Booking element : bookable) {
Terminal.printLine(toString(element));
}
}
public static String toString(Booking element) {
return "000" + busNumber + " " + start + " " + destination + " " + price + " " + currency;
}
}
My second class which is later supposed to be the UI:
public class Input {
public static void main(String[] args) {
Booking.add(new Booking(1, "Mannheim", "Karlsruhe", 2.05, Currency.EUR));
Booking.add(new Booking(2, "Heidelberg", "Karlsruhe", 3.05, Currency.JPY));
Booking.add(new Booking(3, "Germersheim", "Karlsruhe", 4.05, Currency.USD));
Booking.listRoute();
}
}
The Output is: "0003, "Germersheim", "Karlsruhe", 4.05, Currency.USD" 3 times..

how I can put a dynamic filtered xpage view / repeat control into a hashmap?

Can I easily put the entry values of a filtered view into a hashmap?
I have a repeat control, bound to a view, with a dynamic filter.
The user can change the filter by several djFilteringSelect controls, corresponding to the view columns.
Depending on the selection in the 1st djFilteringSelect, the selection in the next djFilteringSelects should be limited to the possible entries ("similar to the data filter in excel"). At the moment I do this with separate #dbcolumn/#dblookup methods for the djFilteringSelects, but I think it is much better and easier to just fill the view entries values into a hashmap and show the hashmap values in the djFilteringSelect.
I found few threads here with repeat controls and hashmaps, but these examples also build the doc collection separatly, which I wish to avoid.
Thanks for any help,
Uwe
There's a reason why all these examples build their document collections separately. Instead of "the view is in the UI", so I must use it, you might have an easier time to build a bean that serves as the source for your repeat control. A bean data source or a managed bean. This will allow for a use case, where you show 2 filter results (e.g England/London and France/Lyon) in one display, something a filtered view can't do.
Update
If you have a lot of reader/author fields, you want to have a view categorized by them, to populate your "backing bean" - there is lot of performance to gain. Holding a few hundred items in memory isn't a big deal.
There are 2 trains of though: make it generic, so every line in the view ends up as a Collection item (Array, List, Map etc.) or to build dedicated line items with clear names. This trains collide quite often, let me take you to the dedicated train for a moment. :-) So your classes (you need 2) would look like this:
package test;
import java.io.Serializable;
import java.util.Vector;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.ViewEntry;
public class Fruit implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String color;
private String shape;
private String taste;
private String unid = null;
public Fruit() {
// default constructor, might not be needed
}
// To make it easy from a view
public Fruit(final ViewEntry ve) {
try {
#SuppressWarnings("rawtypes")
Vector v = ve.getColumnValues();
// 0 would be the user/group/role
this.setName(v.get(1).toString());
this.setColor(v.get(2).toString());
this.setShape(v.get(3).toString());
this.setTaste(v.get(4).toString());
this.unid = ve.getUniversalID();
} catch (NotesException e) {
e.printStackTrace();
}
}
public void save(Database db) throws NotesException {
Document doc;
if (this.unid == null) {
doc = db.createDocument();
} else {
doc = db.getDocumentByUNID(this.unid);
}
doc.replaceItemValue("Color", this.getColor());
// more here
doc.save();
}
public final String getName() {
return this.name;
}
public final void setName(String name) {
this.name = name;
}
public final String getColor() {
return this.color;
}
public final void setColor(String color) {
this.color = color;
}
public final String getShape() {
return this.shape;
}
public final void setShape(String shape) {
this.shape = shape;
}
public final String getTaste() {
return this.taste;
}
public final void setTaste(String taste) {
this.taste = taste;
}
}
That's to hold a line item (using my favourite fruits example). In your code the repeat control variable (or the data table variable) - instead of the view control, would hold one Fruit instance coming from fruitController.getSelectedFruits() (which you can use in EL as fruitController.selectedFruits), so you can bind your columns using varName.color, varname.shape
The class around it looks roughly like:
package test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import lotus.domino.Database;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.View;
import lotus.domino.ViewEntry;
import lotus.domino.ViewEntryCollection;
public class FruitController implements Serializable {
private static final long serialVersionUID = 1L;
private static final String FRUIT_VIEW = "(FruitsByUser)";
private final Collection<Fruit> allFruits = new ArrayList<Fruit>();
private final Set<String> colors = new TreeSet<String>();
private final Set<String> shape = new TreeSet<String>();
private final Set<String> taste = new TreeSet<String>();
private String colorFilter = null;
private String tasteFilter = null;
private String shapeFilter = null;
// if you use this controller, you only can use an object data source!
// for a bean you would need an empty controller
public FruitController(final Session s, final Database db) {
this.populateData(s, db);
}
public final String getColorFilter() {
return this.colorFilter;
}
public final String[] getColors() {
return (String[]) this.colors.toArray();
}
public Collection<Fruit> getSelectedFruits() {
Collection<Fruit> result = new ArrayList<Fruit>();
for (Fruit f : this.allFruits) {
if (this.matchesFilter(f)) {
result.add(f);
}
}
return result;
}
public final String[] getShape() {
return (String[]) this.shape.toArray();
}
public final String getShapeFilter() {
return this.shapeFilter;
}
public final String[] getTaste() {
return (String[]) this.taste.toArray();
}
public final String getTasteFilter() {
return this.tasteFilter;
}
public void resetFilters() {
this.setColorFilter(null);
this.setShapeFilter(null);
this.setTasteFilter(null);
}
public final void setColorFilter(String colorFilter) {
this.colorFilter = colorFilter;
}
public final void setShapeFilter(String shapeFilter) {
this.shapeFilter = shapeFilter;
}
public final void setTasteFilter(String tasteFilter) {
this.tasteFilter = tasteFilter;
}
private boolean matchesFilter(Fruit f) {
boolean result = true;
result = ((result == false) ? false : ((this.colorFilter == null || "".equals(this.colorFilter.trim())) ? true
: (this.colorFilter.equals(f.getColor()))));
result = ((result == false) ? false : ((this.tasteFilter == null || "".equals(this.tasteFilter.trim())) ? true
: (this.tasteFilter.equals(f.getTaste()))));
result = ((result == false) ? false : ((this.shapeFilter == null || "".equals(this.shapeFilter.trim())) ? true
: (this.shapeFilter.equals(f.getShape()))));
return result;
}
private void populateData(final Session s, final Database db) {
try {
final View v = db.getView(FRUIT_VIEW);
// You might need to loop a little here to get all the values
final ViewEntryCollection vec = v.getAllEntriesByKey(s.getUserName());
ViewEntry ve = vec.getFirstEntry();
while (ve != null) {
ViewEntry nextVe = vec.getNextEntry(ve);
Fruit f = new Fruit(ve);
this.updateSelectors(f);
this.allFruits.add(f);
ve = nextVe;
nextVe.recycle();
}
vec.recycle();
v.recycle();
} catch (NotesException e) {
// TODO Stacktrace is no error handling
e.printStackTrace();
}
}
private void updateSelectors(Fruit f) {
this.colors.add(f.getColor());
this.shape.add(f.getShape());
this.taste.add(f.getTaste());
}
}
Of course you can make that more sophisticated by filtering the selection values based on the other selections (e.g. after picking a color only offer the shapes that are available in that color). Using the class as object datasource (e.g. fruitController) should be easy. You can bind your dropdowns to fruitController.colorFilter etc. in EL and define the selections in EL as fruitController.Colors.
Update 2
The data source should be an object data source, like this one:
<xp:this.data>
<xe:objectData var="fruitController" ignoreRequestParams="true"
readonly="false" scope="view"
createObject="#{javascript:return new test.FruitController(session, database);}">
</xe:objectData>
</xp:this.data>
For a bean approach you would need to edit the faces-config.xml and change the class to have a parameterless constructor. For the select values you could stick with the toArray() call in your page or better change the class to return an array in the first place. I updated the class above accordingly (so you can still use EL, no need for SSJS).
Now you only need to add a refresh to the repeat in the onChange event of your selects. Since the new values will be send to the object data source (you bound them to colorFilter, shapeFilter, tasteFilter) the refresh will execute #{fruitController.selectedFruits} which delivers the subset back to the panel.
So the concept here is: You fetch all the user data once into the object data source and once that is loaded filter inside that class, no renewed retrieval or lookup required.
Let us know hoe it goes

How to Store objects in an ArrayList when you do not know how many object you need to create?

Back ground: I am pairing up two pieces of data, both Strings, into an ArrayList. Therefore I am storing the paired data into an object, and then storing this object into an ArrayList. I have a text file that for each word, I am assigning a number to. The paired data is then word-number (but I have typed them both as String). I do not know how many objects I will need for any given file size.
How do I set up a logic to iterate through the text file and populate my ArrayList. This is what I have done so far:
The : PredictivePrototype.wordToSignature(aWord)// converts the word into a number signature e.g "4663" for a word like "home"
public class ListDictionary {
private static ArrayList<WordSig> dictionary;
public ListDictionary() throws FileNotFoundException {
File theFile = new File("words");
Scanner src = new Scanner(theFile);
while (src.hasNext()) {
String aWord = src.next();
String sigOfWord = PredictivePrototype.wordToSignature(aWord);
// assign each word and its corresponding signature into attribute
// of an object(p) of class WordSig.
//WordSig p1 = new WordSig(aWord, sigOfWord);
//Then add this instance (object) of class Wordsig into ArrayList<WordSig>
dictionary.add(new WordSig(aWord, sigOfWord));
}
src.close();
}
Other class to which paired data is stored:
public class WordSig {
private String words;
private String signature;
public WordSig(String words, String signature) {
this.words=words;
this.signature=signature;
}
}
Your code seems to be OK. With ArrayList you can add as many elements as you want (by using add() function).
Here is an example:
import java.util.ArrayList;
public class ListDictionary {
public class WordSig {
private String words;
private String signature;
public WordSig(String words, String signature) {
this.words=words;
this.signature=signature;
}
public String getWords() {
return words;
}
public String getSignature() {
return signature;
}
}
private static ArrayList<WordSig> dictionary = new ArrayList<WordSig>();
public ListDictionary() {
// add as many as you want
for ( int i=0; i < 10; i++)
dictionary.add(new WordSig("key"+i, "value"+i));
}
public static class testListDictionary {
public static void main(String[] args) {
new ListDictionary();
// test output
for ( int i=0; i < dictionary.size(); i++ )
System.out.println( "<" + dictionary.get(i).getWords() + "|"
+ dictionary.get(i).getSignature() + ">");
}
}
}

Java: Sorting text file lines

I'm using eclipse and I'm trying to sort a text file with about 40 lines that look like this:
1,Terminator,1984,Schwarzenegger
2,Avatar,2009,Worthington
3,Avengers,2012,Downey
4,Starwars,1977,Hammill
5,Alien,1979,Weaver
I want sort them alphabetically by the second field so that the text file is altered to look like this:
5,Alien,1979,Weaver
2,Avatar,2009,Worthington
3,Avengers,2012,Downey
4,Starwars,1977,Hammill
1,Terminator,1984,Schwarzenegger
I'm fairly certain I should be doing something involving tokenizing them (which I've already done to display it) and a BufferedWriter but I can't for the life of me think of a way to do it by the second or third field and I feel like I'm missing something obvious.
You will first of course need to read a file, which you can learn how to do here.
Java: How to read a text file
This example will provide several ways you may write the file once you have sorted your data.
How do I create a file and write to it in Java?
As for sorting, I recommend creating a class Movie, which would look similar to
public class Movie implements Comparable<Movie> {
private String name;
private String leadActor;
private Date releaseDate;
public Movie(String name, String leadActor, String releaseDate) {
}
#Override
public int compareTo(Movie other) {
}
}
Ill leave it to you fill in the rest of the constructor and compareTo method. Once you have your compareTo method you will be able to call Collections.sort(List list) passing your list of Movie.
Here are some resources on implementing Comparable.
http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
Why should a Java class implement comparable?
Your comparator
class SampleComparator implements Comparator<String> {
#Override
public int compare(String o1, String o2) {
String array1[] = o1.split(",");
String array2[] = o2.split(",");
return array1[1].compareTo(array2[1]);
}
}
Your Sorting
String [] lines= {"1,Terminator,1984,Schwarzenegger",
"2,Avatar,2009,Worthington",
"3,Avengers,2012,Downey",
"4,Starwars,1977,Hammill",
"5,Alien,1979,Weaver"};
List<String> rowList = new ArrayList<String>(Arrays.asList(lines));
Collections.sort(rowList, new SampleComparator());
for (String string : rowList) {
System.out.println(string);
}
Your Output
5,Alien,1979,Weaver
2,Avatar,2009,Worthington
3,Avengers,2012,Downey
4,Starwars,1977,Hammill
1,Terminator,1984,Schwarzenegger
If you have any doubt on this let me know..
The String class has a very helpful static method called "split". All you do is call split and put it in the delimiter and it gives back a String array with the split up string.
Here's an example:
String line = "How,Now,Brown,Cow";
String[] splitLine = line.split(",");
for(String l: splitLine)
{
System.out.println(l);
}
The above code would print the following:
How
Now
Brown
Cow
Hopefully you can use this and adapt it to your problem.
Good luck!
What you want to do is to use java.util.Comparator and Collections.sort. More on this can be found: http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
Following #Tyler answer. You can have a default implementation in the Movie class and additional sort orders that you can implement by calling Collections.sort(movieList, new MyComparator()); Here comes an example of both.
package com.stackoverflow;
public class Movie implements Comparable<Movie> {
private String name;
private String leadActor;
private String releaseDate;
public Movie(String name, String leadActor, String releaseDate) {
this.name = name;
this.leadActor = leadActor;
this.releaseDate = releaseDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLeadActor() {
return leadActor;
}
public void setLeadActor(String leadActor) {
this.leadActor = leadActor;
}
public String getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(String releaseDate) {
this.releaseDate = releaseDate;
}
#Override
public int compareTo(Movie other) {
return getName().compareTo(other.getName());
}
}
And if you want to make your own comparator called on your collection:
package com.stackoverflow;
import java.util.Comparator;
public class MyComparator implements Comparator<Movie> {
#Override
public int compare(Movie o1, Movie o2) {
return o1.getLeadActor().compareTo(o2.getLeadActor());
}
}
Try like this :--
ArrayList ar=new ArrayList();
String [] arr=new String[10];
int i=0;
try {
Scanner sc=new Scanner(file);
while (sc.hasNextLine())
{
String ss=sc.nextLine();
i=i+1;
arr[i]=ss;
}
ar.add(arr[5]);
ar.add(arr[2]);
ar.add(arr[3]);
ar.add(arr[4]);
ar.add(arr[1]);
System.out.println(ar);
}
This solution uses Java 8 APIs.
You don't really need to have an explicit implementation of Comparator or create a Comparable class. Using Comparator.comparing with lambda we can elegantly sort lines by custom key.
import java.io.IOException;
import java.nio.file.*;
import java.util.Comparator;
import java.util.stream.Stream;
public class FileSortWithStreams {
public static void main(String[] args) throws IOException {
Path initialFile = Paths.get("files/initial.txt");
Path sortedFile = Paths.get("files/sorted.txt");
int sortingKeyIndex = 1;
String separator = ",";
Stream<CharSequence> sortedLines =
Files.lines(initialFile)
.map(s -> s.split(separator))
.sorted(Comparator.comparing(s -> s[sortingKeyIndex]))
.map(s -> String.join(separator, s));
Files.write(sortedFile, sortedLines::iterator, StandardOpenOption.CREATE);
}
}

Categories