In this program I need to display an array list from an external file in descending order. Whenever I run the program though, I still get the same order of the original list. I just need help with the descending order part. I utilized the Collections methods to accomplish this task but I don't think I fully understand exactly what is going on whenever I call upon Collections, it just spits out the array list as brought in by the first array call. Any help would be greatly appreciated. I placed 4 stars at the end and beginning of the code in question.
import java.io.*;
import java.util.*;
public class ioStafford {
public static void revOrder(String x[])
{
}
public static void main(String args[])
{
try(BufferedReader fr1 = new BufferedReader(new FileReader("myImport.txt")))
{
//Create a new file for the reverse output if it doesn't exist
File f1 = new File("myOutput.txt");
//Code for new file creation
if(!f1.exists())
{
f1.createNewFile();
}
//Initialize string variables
String type;
//Array List to hold text file
ArrayList<String> names = new ArrayList<String>();
//Add text file contents to the array list
while((type = fr1.readLine()) != null)
{
names.add(type);
}
//Display array list
System.out.println("Below is the list of animals with a comma and in the original order:");
System.out.println(names);
****//Display information in descending order
Collections.sort(names, Collections.reverseOrder());
System.out.println(names);****
//Convert array list to string and replace commas
String fornames = names.toString().replace("," , " ");
//Display altered information
System.out.println("Here is the list with the commas removed:");
System.out.println(fornames);
}
catch(FileNotFoundException e)
{
System.out.println("Please utilize the file named myImport.txt please!");
}
catch(IOException e)
{
}
}
}
Try this one in a place of
Collections.sort(names, Collections.reverseOrder());
:->
Collections.sort(names, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
Related
Would Collections.sort() work in sorting by Make in a Car object Array List? I'm getting no error messages after adding the null there, but my goal is to sort them by Make, specifically, but I'm not entirely sure how to go about doing that.
public void readingFromFile(String file) throws FileNotFoundException //an object array that takes in string files
{
try {
File myFile = new File(file); //converts the parameter string into a file
Scanner scanner = new Scanner(myFile); //File enables us to use Scanner
String line = scanner.nextLine(); //reads the current line and points to the next one
StringTokenizer tokenizer = new StringTokenizer(line, ","); //tokenizes the line, which is the scanned file
//counts the tokens
while (tokenizer.hasMoreTokens()){
String CarMake = tokenizer.nextToken(); //since car is in order by make, model, year, and mileage
String CarModel = tokenizer.nextToken();
int CarYear1 = Integer.parseInt(tokenizer.nextToken());
int CarMileage1 = Integer.parseInt(tokenizer.nextToken()); //converts the String numbers into integers
Car cars = new Car(CarMake, CarModel, CarYear1, CarMileage1); //since the car has a fixed order
arraylist.add(cars); //add the cars to the unsorted array
}
scanner.close(); //close the scanner
} catch (FileNotFoundException f){
f.printStackTrace();
return;
}
arraylist2.addAll(arraylist);
Collections.sort(arraylist2, null);
}
Use the streaming API:
sorted = arrayList2.stream().sorted(Comparator.comparing(Car::getMake));
Since Java 8 the List has a sort method inherited by Collection. Additionally you can use the Comparator class to create a comparator very easy:
arraylist2.sort(Comparator.comparing(Car::getMake));
If you want to use multiple Parameters for your sort you can easily append them:
arraylist2.sort(Comparator.comparing(Car::getMake)
.thenComparing(Car::getYear)
// ...
);
If you are using a Java Version below Java 8 you have to implement the sort logic yourself in an Comparator or use an external library:
Collections.sort(arraylist2, new Comparator<Car>() {
#Override
public int compare(Car a, Car b) {
return a.getMake().compareTo(b.getMake());
}
});
For multiple parameters it would look like the following:
Collections.sort(arraylist2, new Comparator<Car>() {
#Override
public int compare(Car a, Car b) {
int compareMake = a.getMake().compareTo(b.getMake());
if (compareMake != 0) {
return compareMake;
}
return a.getYear() - b.getYear();
}
});
I'm writing the code of my first Java game right now and I have a problem with ArrayList. I have one, with elements like nicknames and scores, to be specific I create it from the text file(code below):
static ArrayList<String> results = new ArrayList<String>();
BufferedReader br = new BufferedReader(new FileReader(ranking));
String line = br.readLine();
results.add(line);
while(line != null) {
line = br.readLine();
results.add(line);
}
br.close();
So the file looks like this:
nick1
score1
nick2
score2
...
I would like to make a ranking with top 10 best results, my idea is to make the class with the fields nick and score and somehow assign that fields to appriopriate ones from the ArrayList. Maybe I can do this like this:(?)
for(int i = 0;i<results.size();i=i+2){
nick = results.get(i);
}
for(int i = 1;i<results.size();i=i+2){
score = results.get(i);
}
Then I would create a new ArrayList, which would be in the type of that new class. But my problem is that I don't exactly know how I can connect values from 'old' ArrayList with the paramaters of future type of new ArrayList. The new one should be like:
static ArrayList<Ranking> resultsAfterModification = new ArrayList<Ranking>();
Ranking rank = new Ranking(nick, score);
Then I can easily compare players' scores and make a solid ranking.
You can create a class Player that contains the name and score of each player. The Player class should implement the Comparable interface which is Java's way of figuring out the logical order of elements in a collection:
public class Player implements Comparable<Player>
{
private String _name;
private double _score;
public Player(String name, double score)
{
this._name = name;
this._score = score;
}
public String getName()
{
return this._name;
}
public double getScore()
{
return this._score;
}
// Since you probably want to sort the players in
// descending order, I'm comparing otherScore to this._score.
#Override
public int compareTo(Player otherScore)
{
return Double.compare(otherScore._score, this._score);
}
#Override
public String toString()
{
return "Name: " + this._name + ", Score: " + Double.toString(this._score);
}
}
Once you've created the Player class, you can read both name and score in one go and use the Collections utility class to sort the Player list. Last but not least, you could grab the top ten by using the subList method: (this assumes that the file will have a score for each name and the file will be in the format you specified above)
public static void main(String[] args)
{
List<Player> results = new ArrayList<Player>();
BufferedReader br;
try
{
br = new BufferedReader(new FileReader("myFile.txt"));
String line = br.readLine();
while(line != null)
{
String name = line;
double score = Double.parseDouble(br.readLine());
results.add(new Player(name, score));
line = br.readLine();
}
br.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
// Sort using the java.util.Collections utility class
// Sorting will modify your original list so make a copy
// if you need to keep it as is.
Collections.sort(results);
// Top 10
List<Player> top10 = results.subList(0, 10);
}
1) You should program by Interface (List instead of ArrayList in declared type) here because you don't use methods specific to ArrayList.
List<Ranking> resultsAfterModification = new ArrayList<Ranking>();
2)
Then I would create a new ArrayList, which would be in the type of
that new class. But my problem is that I don't exactly know how I can
connect values from 'old' ArrayList with the paramaters of future type
of new ArrayList.
To do it, you don't need many changes.
Your idea a is little too complex because finally you perform two mappings : one where you store from read line to List of String and another one where you store from List of String to List of Ranking .
You can direct map read line to List of Ranking.
List<Ranking> rankings = new ArrayList<Ranking>();
BufferedReader br = new BufferedReader(new FileReader(ranking));
String nick = null;
while ( (nick = br.readLine()) != null){
String score = br.readLine();
rankings.add(new Ranking(nick, score));
}
You can save array in file :
1 use, FileInputStram and FileOuputStream to write and read array object to file.
2 use Gson library to save and load array as json
3 write as normal textfile like below:
Player 1
Score 1
Player 2
Score 2
....
ArrayList<Player> list=new ArrayList();
Scanner sc=new Scanner(new File("filepath.txt"));
While(sc.hasNextLine()){
Player p=new Player();
p.name=sc.nextLine();
If(sc.hasNextFloat()){
p.score=sc.nextFloat();
list.add(p);
}
}
Arrays.sort(list,...);
And can sort array by Arrays.sort()
So your Ranking class might look like
public class Ranking {
public String nick;
public int score;
}
I think the nick and score are two ArrayList containing nicks and scores respectively.
So to create a common ArrayList, if the sizes of nick and score are the same, you might do something like this.
static ArrayList<Ranking> resultsAfterModification = new ArrayList<Ranking>();
for(int i = 0; i < nick.size(); i++) {
Ranking rank = new Ranking(nick.get(i), score.get(i));
resultsAfterModification.add(rank);
}
Now you need to write your own comparator to sort the values inside resultsAfterModification
Collections.sort(resultsAfterModification, new Comparator<Ranking>() {
#Override
public int compare(Ranking r1, Ranking r2) {
if (r1.score > r2.score)
return 1;
if (r1.score < r2.score)
return -1;
return 0;
}
});
I'm messing around trying to learn to use HashSets to remove duplicate elements in my output but I'm running into some trouble.
My goal is to select a text file when the program is run and for it to display the words of the text file without duplicates, punctuation, or capital letters. All of it works fine except for removing the duplicates.
This is my first time using a Set like this. Any suggestions as to what I'm missing? Thanks!
Partial text file input for example: "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation, so conceived and so dedicated, can long endure"
import java.util.Scanner;
import java.util.List;
import java.io.*;
import java.util.*;
import javax.swing.JFileChooser;
public class Lab7 {
public interface OrderedList<T extends Comparable<T>> extends Iterable<T>
{
public void add(T element);
public T removeFront();
public T removeRear();
public int size();
public boolean isEmpty();
public boolean contains(T element);
public Iterator<T> iterator();
}
public static void main(String[] arg) throws FileNotFoundException
{
Scanner scan = null;
JFileChooser chooser = new JFileChooser("../Text");
int returnValue = chooser.showOpenDialog(null);
if( returnValue == JFileChooser.APPROVE_OPTION)
{
File file = chooser.getSelectedFile();
scan = new Scanner(file);
}
else
return;
int count = 0;
Set<String> set = new LinkedHashSet<String>();
while(scan.hasNext())
{
String[] noDuplicate = {scan.next().replaceAll("[\\W]", "").toLowerCase()};
List<String> list = Arrays.asList(noDuplicate);
set.addAll(list);
count++;
}
scan.close();
System.out.println(set);
System.out.println();
System.out.println(chooser.getName() + " has " + count + " words.");
}
}
Your problem is that you are creating a new HashSet every time you read a word using the Scanner, so there is no chance for it to do de-duplication. You can fix it with the following steps. Also, normal HashSet does not retain ordering.
Create the HashSet once, before the Scanner loop.
Use a LinkedHashSet, so that order is preserved in the same order that you added it.
Inside the loop, use set.add(item);. As the other answer mentions, you do not need to create a one-element list.
Adding the code for completeness.
public static void main(String[] arg) throws FileNotFoundException
{
Scanner scan = null;
scan = new Scanner(new File("Input.txt"));
int count = 0;
Set<String> set = new LinkedHashSet<String>();
while(scan.hasNext())
{
String word = scan.next().replaceAll("[\\W]", "").toLowerCase();
set.add(word);
count++;
}
scan.close();
// System.out.println(set);
System.out.println();
System.out.println("Input.txt has " + count + " words.");
// How do I print a set by myself?
for (String word : set) {
// Also remove commas
System.out.println(word.replaceAll(",",""));
}
}
I would do it this way:
Set<String> set = new LinkedHashSet<String>();
while(scan.hasNext())
{
String noDuplicate = scan.next().replaceAll("[\\W]", "").toLowerCase();
set.add(noDuplicate);
}
scan.close();
System.out.println("The text has " + set.size() + " unique words.");
Your solution (Creating a one element array, converting that to a List, and converting that to a HashSet) is extremely inefficient, in addition to being incorrect. Just use the String you're originally working with, and add it to the LinkedHashSet (which will preserve ordering). At the end set.size() will show you the number of unique words in your sentence.
This question already has answers here:
How to sort an arraylist of objects java?
(6 answers)
Closed 9 years ago.
I have a problem.
I want to sort Strings from txt file by the numbers of characters in String
For example
Input:
aaa
a
aa
Output:
a
aa
aaa
I created Collection that contain strings by alphabet & created collection that contain number of String characters, but i can't understand
How I can sort by the numbers of characters in String
public class SortingFile {
public static void main(String[] args) throws IOException {
try{
File inputFile=new File("c:/a.txt");
Reader r=new FileReader(inputFile);
BufferedReader br=new BufferedReader(r);
List <String> list = new LinkedList<String>();
List <Integer> listLength= new LinkedList<Integer>();
String line=br.readLine();
list.add(line);
while (line!=null){
line=br.readLine();
list.add(line);
}
int arrsize=(list.size())-1;
System.out.println("line array size= "+arrsize);
list.remove(arrsize); //delete last element (he is null )
System.out.println("Before sorting by alphabet: "+list);
Collections.sort(list);//sorting by alphabet
System.out.println("After sorting by alphabet: " +list);
for (int i=0;i!=list.size();i++){ //add string lenght to collection
String a=list.get(i);
int aa=a.length();
listLength.add(aa);
}
System.out.println("lineLength:"+listLength);
Collections.sort(listLength); // sotring by asc
System.out.println("lineLength2:"+listLength);
br.close();
}catch (FileNotFoundException e1){
System.out.println("File ''a.txt'' Not Found :(");
e1.printStackTrace();
}
}
}
Try, with following Comparator
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
Use Collections.sort(java.util.List, java.util.Comparator) which takes an additional Comparator argument.
That allows you to change the way things are sorted.
Collections.sort has an overloaded method where you can give a comparator. Code a comparator where you will compare the length of the strings and return whatever is greater or smaller (depending upon whether you want ascending or descending order). then just invoke your Collections.sort(myListOfString,myComporator); and the result would be a list of strings ordered by length.
Pass comparator to your Collection.sort(list,yourSorter) method and use whatever logic you want to use in it.
Collections.sort(list, sortAccordingToLength);
static Comparator<String> sortAccordingToLength= new Comparator<String> {
public int compare(String a, String b) {
return a.length()-b.length();
}
});
I am piping in a file. I am tracking word pairs from the file. Using a treemap the keys are all sorted. However, when i add words to those keys they are not sorted.
here is the part i need help on in the process function:
private static void process(){
if(!result.containsKey(thisWord)){
result.put(thisWord, new ArrayList<String>());
}
// Add nextWord to the list of adjacent words to thisWord:
result.get(thisWord).add(nextWord); // nextword is not sorted within the key
thisword is sorted
nextWord is not..
Can i use Collections.sort(result); somehow?
im just not sure how i get to the nextWord within the result to do that.
or, is there no way to do it within my situation. I would rather not change things unless you recommend it.
This is the program
import java.util.Map.Entry;
import java.util.TreeSet;
import java.io.*;
import java.util.*;
public class program1 {
private static List<String> inputWords = new ArrayList<String>();
private static Map<String, List<String>> result = new TreeMap<String, List<String>>();
public static void main(String[] args) {
collectInput();
process();
generateOutput();
}
private static void collectInput(){
Scanner sc = new Scanner(System.in);
String word;
while (sc.hasNext()) { // is there another word?
word = sc.next(); // get next word
if (word.equals("---"))
{
break;
}
inputWords.add(word);
}
}
private static void process(){
// Iterate through every word in our input list
for(int i = 0; i < inputWords.size() - 1; i++){
// Create references to this word and next word:
String thisWord = inputWords.get(i);
String nextWord = inputWords.get(i+1);
// If this word is not in the result Map yet,
// then add it and create a new empy list for it.
if(!result.containsKey(thisWord)){
result.put(thisWord, new ArrayList<String>());
}
// Add nextWord to the list of adjacent words to thisWord:
result.get(thisWord).add(nextWord); // need to sort nextword
// Collections.sort(result);
}
}
private static void generateOutput()
{
for(Entry e : result.entrySet()){
System.out.println(e.getKey() + ":");
// Count the number of unique instances in the list:
Map<String, Integer> count = new HashMap<String, Integer>();
List<String> words = (List)e.getValue();
for(String s : words){
if(!count.containsKey(s)){
count.put(s, 1);
}
else{
count.put(s, count.get(s) + 1);
}
}
// Print the occurances of following symbols:
for(Entry f : count.entrySet()){
System.out.println(" " + f.getKey() + ", " + f.getValue() );
}
}
System.out.println();
}
}
If you want the collection of "nextword"s sorted, why not use a TreeSet rather than an ArrayList? The only reason I can see against it is if you might have duplicates. If duplicates are allowed, then yes, use Collections.sort on the ArrayList when you're done adding to them. Or look in the Apache Commons or Google collection classes - I don't know them off the top of my head, but I'm sure there is a sorted List that allows duplicates in one or both of them.
result.get(thisWord).add(nextWord);
Collections.sort(result.get(thisWord));
Y Don't you try some thing like this
Collections.sort(inputWords);