How to sort Arraylist of objects - java

I have ArrayList, which containst football teams (class Team). Teams have points and i want to sort them by number of points.
public class Team {
private int points;
private String name;
public Team(String n)
{
name = n;
}
public int getPoints
{
return points;
}
public void addPoints(boolean win)
{
if (win==true)
{
points = points + 3;
}
else if (win==false)
{
points = points + 1;
}
}
//...
}
Main Class:
List<Team> lteams = new ArrayList<Team>;
lteams.add(new Team("FC Barcelona"));
lteams.add(new Team("Arsenal FC"));
lteams.add(new Team("Chelsea"));
//then adding 3 points to Chelsea and 1 point to Arsenal
lteams.get(2).addPoints(true);
lteams.get(1).addPoints(false);
//And want sort teams by points (first index with most points).
I did my comparator.
public class MyComparator implements Comparator<Team> {
#Override
public int compare(Team o1, Team o2) {
if (o1.getPoints() > o2.getPoints())
{
return 1;
}
else if (o1.getPoints() < o2.getPoints())
{
return -1;
}
return 0;
}
}
now I wanna use it (in main class)
Colections.sort(lteams, new MyComparator());
I want to see:
Chelsea
Arsenal
Barcelona
But it doesn't sort.

Source : Here
You can use Collections.sort with a custom Comparator<Team>.
class Team {
public final int points;
// ...
};
List<Team> players = // ...
Collections.sort(players, new Comparator<Team>() {
#Override public int compare(Team p1, Team p2) {
return p1.points- p2.points;
}
});
Alternatively, you can make Team implementsComparable<Team>. This defines the natural ordering for all Team objects. Using a Comparator is more flexible in that different implementations can order by name, age, etc.
See also
Java: What is the difference between implementing Comparable and Comparator?
For completeness, I should caution that the return o1.f - o2.f comparison-by-subtraction shortcut must be used with extreme caution due to possible overflows (read: Effective Java 2nd Edition: Item 12: Consider implementing Comparable). Presumably hockey isn't a sport where a player can score goals in the amount that would cause problems =)
See also
Java Integer: what is faster comparison or subtraction?

public class Team {
private int points;
private String name;
public Team(String n, int p) {
name = n;
points = p;
}
public int getPoints() {
return points;
}
public String getName() {
return name;
}
public static void main(String[] args) {
List<Team> lteams = new ArrayList<Team>();
lteams.add(new Team("FC Barcelona", 0));
lteams.add(new Team("Arsenal FC", 2));
lteams.add(new Team("Chelsea", 3));
Collections.sort(lteams, new MyComparator());
for (Team lteam : lteams) {
System.out.println(lteam.name + ": " + lteam.points + " points");
}
}
}
class MyComparator implements Comparator<Team> {
#Override
public int compare(Team o1, Team o2) {
if (o1.getPoints() > o2.getPoints()) {
return -1;
} else if (o1.getPoints() < o2.getPoints()) {
return 1;
}
return 0;
}}
Output:
Chelsea: 3 points
Arsenal FC: 2 points
FC Barcelona: 0 points

It is not actually necessary to define a custom Comparator like this.
Instead, you can easily define one, when you want to sort your ArrayList.
Since JAVA 8 using lamda
// Sort version.
Iteams.sort(Comparator.comparing(Team::getPoints));
// Complete version.
Iteams.sort((o1, o2) -> o1.getPoints().compareTo(o2.getPoints()));
Also there are options for second comparator, if objects are equals on the first:
// e.g. if same points, then compare their names.
Iteams.sort(Comparator.comparing(Team::getPoints).thenComparing(Team::getName));
Also note that the default sort option is ascending, but you can set it to descending using:
// e.g. Sort by points descending.
Iteams.sort(Comparator.comparing(Team::getPoints).reversed());
That way, you can sort your ArrayList in different ways whenever you want, just by adding the method you want.

Related

Why is remove() for TreeSet<String> not working?

I am trying to solve the problem at https://leetcode.com/problems/design-a-food-rating-system and this is my solution.
class FoodRatings {
class SortedSetComparator implements Comparator<String> {
public int compare(String A, String B) {
if (foodRatingMap.get(A) == foodRatingMap.get(B)) {
return A.compareTo(B);
}
return foodRatingMap.get(B).compareTo(foodRatingMap.get(A));
}
}
Map<String, SortedSet<String>> foodTypeMap;
Map<String, String> foodMap;
Map<String, Integer> foodRatingMap;
public FoodRatings(String[] foods, String[] cuisines, int[] ratings) {
foodTypeMap = new HashMap<>();
foodMap = new HashMap<>();
foodRatingMap = new HashMap<>();
for (int i = 0; i<foods.length; i++) {
foodTypeMap.putIfAbsent(cuisines[i], new TreeSet<String> (new SortedSetComparator()));
foodMap.put(foods[i], cuisines[i]);
foodRatingMap.put(foods[i], ratings[i]);
foodTypeMap.get(cuisines[i]).add(foods[i]);
}
}
public void changeRating(String food, int newRating) {
foodRatingMap.put(food, newRating);
SortedSet<String> set = foodTypeMap.get(foodMap.get(food));
if (!set.remove(food)) {
System.out.println("Unable to find " + food);
}
foodTypeMap.get(foodMap.get(food)).add(food);
}
public String highestRated(String cuisine) {
return foodTypeMap.get(cuisine).first();
}
}
Could anyone tell me why the TreeSet remove() method is not working ?
Here is the input for the same.
public static void main(String args[]) {
String[] foods = new String[] {
"czopaaeyl", "lxoozsbh", "kbaxapl"
};
String[] cuisines = new String[] {
"dmnuqeatj", "dmnuqeatj", "dmnuqeatj"
};
int[] ratings = new int[] {
11, 2, 15
};
FoodRatings obj = new MyClass().new FoodRatings(foods, cuisines, ratings);
obj.changeRating("czopaaeyl", 12);
String food = obj.highestRated("dmnuqeatj");
System.out.println(food);
obj.changeRating("kbaxapl", 8);
food = obj.highestRated("dmnuqeatj");
System.out.println(food);
obj.changeRating("lxoozsbh", 5);
food = obj.highestRated("dmnuqeatj");
System.out.println(food);
}
I am not sure why the remove function is not working properly here.
Well, it took me a while to find the problem. Besides the Integer compare issue which is only needed to sort equal ratings in lexical order. You were updating the ratings prior to doing a remove. But since your set uses this structure in its comparator, things got out of sync.
public void changeRating(String food, int newRating) {
SortedSet<String> set = foodTypeMap.get(foodMap.get(food));
if (!set.remove(food)) {
System.out.println("Unable to find " + food);
}
foodTypeMap.get(foodMap.get(food)).add(food);
foodRatingMap.put(food, newRating);
}
As soon as I moved foodRatingMap.put(food, newRating); to the bottom, it worked. BTW, I would have written a Food class hold each foods type, rating, and cuisine. Usually these test sites are only interested in results and efficiency, not how you did it.
Well. That was a very subtle issue to find. First the order in which the ratings were updated are wrong. The correct order was :-
Remove the food from the sortedSet.
Update the rating.
Add the food back to the sorted set.
Changes were done in two places.
The first one was to correct the order.
public void changeRating(String food, int newRating) {
foodTypeMap.get(foodMap.get(food)).remove(food);
foodRatingMap.put(food, newRating);
foodTypeMap.get(foodMap.get(food)).add(food);
}
The second one was to use equals() when comparing integer values in the comparator.
class SortedSetComparator implements Comparator<String> {
public int compare(String A, String B) {
if (foodRatingMap.get(A).equals(foodRatingMap.get(B))) {
return A.compareTo(B);
}
return foodRatingMap.get(B).compareTo(foodRatingMap.get(A));
}
}

Arranging by Alphabetical Order

I'm new to Java and I'm trying to arrange an arrayList of terms in alphabetical order. (A term is defined as a char and an int) (e.g. {Term('Z',4),Term('C',3),Term('Q',2) ...} )
My code is as follows:
public Term nextElement()
{
Term max = terms.get(0);
char maxtest = max.getElement();
for (int i = 1; i < terms.size(); i++){
Term tester = terms.get(i);
char maxtest2 = tester.getElement();
if (maxtest2 > maxtest) {
tester = max;
}
}
return max;
}
Why isn't this working? and how do I accomplish this?
My arrayList is called term filled with type Term
Your problem with this line of Code. Your class is not a Type of Comparable So, On which property or criteria compareTo() method will compare these two objects ???
res = maxtest.compareTo(maxtest2); //Your maxtest object is not Comparable Type.
You must need to make your class Term Comparable type. and , Override the method compareTo() as per your need.
You have not mentioning the variable's or structure of your class Term . So, I am assuming that your class have such kind of Structure .
public class Term implements Comparable<Term> {
private Character alpha;
private int number;
//getter and setters +Constructors as you specified
....
....
...
.....
// Now Set a criteria to sort is the Alphanumeric.
#Override
public int compareTo(Term prm_obj) {
if (prm_obj.getAlpha() > this.alpha) {
return 1;
} else if (prm_obj.getAlpha() < this.alpha) {
return -1;
} else {
return 0;
}
}
Now Your Class become a comparable Type. So you may apply Collections.sort(Collection obj) which automatically sort your ArrayList<Term>.
Here I write a demo for this.
public static void main(String... args){
List<Term> obj_listTerm = new ArrayList<>();
//add all the data you given in question
obj_listTerm .add(new Term('Z', 4));
obj_listTerm .add(new Term('Q', 2));
obj_listTerm .add(new Term('c', 3));
// print without Sorting your Term ArrayList.
System.out.println("This is the list unsorted: " + myTermList);
// Sort Using Collections.sort() Method.
Collections.sort(myTermList);
// After applying sort() you may see your Sorted ArrayList.
System.out.println("This is the list SORTED: " + myTermList);
}
You can use the Collection class and sort the list of term you have, you need only to make the class Term comparable
Example:
public class Term implements Comparable<Term> {
.....
// .....
// criteria to sort is the char
#Override
public int compareTo(Term o) {
if (o.getLetter()> this.letter) {
return 1;
} else if (o.getLetter() < this.letter) {
return -1;
} else {
return 0;
}
}
public static void main(String[] args) {
// test
List<Term> myTermList = new ArrayList<>();
myTermList.add(new Term('Z', 4));
myTermList.add(new Term('Q', 2));
myTermList.add(new Term('c', 3));
// check how the look like
System.out.println("This is the list unsorted: " + myTermList);
// now sort them
Collections.sort(myTermList);
// check how the look like
System.out.println("This is the list SORTED: " + myTermList);
}
Edit>
if you dont want to implement comparable then modify this:
res = maxtest.compareTo(maxtest2);
because this is not valid since maxtest and maxtest2 are primitives and not objects...
use instead
res = Character.compare(maxtest, maxtest2);
and then use the result to verify your logic and make decisions:
if (res >1) {
System.out.println("bigger");
}else if (res<1) {
System.out.println("smaller");
}else {
System.out.println("same");
}

How to alter a bubble sort from numeric to alphabetical?

I am using an ArrayList with book titles and book ratings. How can I change this code to make the bubble sort for alphabetical instead of numeric?
System.out.println("\r" + "In order by rating");
for (int out = 0; out < bookList.size(); out++) {
for (int in = 0; in < bookList.size() - 1; in++)
if (bookList.get(in).getRating() < bookList.get(in + 1).getRating()) {
Book temp = bookList.get(in);
bookList.set(in, bookList.get(in+1));
bookList.set(in+1, temp);
}
System.out.println(videoList.get(out).getTitle() + " " + videoList.get(out).getRating());
}
}
My other classes are below.
Book
public class Book {
String title;
int rating;
public Book(String pTitle, int pRating) {
title = pTitle;
rating = pRating;
}
public String getTitle() {
return title;
}
public int getRating() {
return rating;
}
public void setTitle(String newTitle) {
title = newTitle;
}
public void setRating(int newRating) {
rating = newRating;
}
}
Library
import java.util.ArrayList;
public class Library {
public static void main (String [] args) {
ArrayList<Book> bookList = new ArrayList<Book>();
Book b1 = new Book ("Huckleberry Finn", 5);
Book b2 = new Book ("The Great Gadsby", 2);
Book b3 = new Book ("Harry Potter", 3);
Book b4 = new Book ("Animal Farm", 4);
Book b5 = new Book ("The Mist", 1);
bookList.add(b1);
bookList.add(b2);
bookList.add(b3);
bookList.add(b4);
bookList.add(b5);
System.out.println("Original sequence");
for (int cnt = 0; cnt < videoList.size(); cnt++) {
System.out.println(bookList.get(cnt).getTitle() + " " + bookList.get(cnt).getRating());
}
}
}
Is there a way to alter the code in the algorithm class to display the bookList sorted by Title?
You can't use < directly on two Strings, but you can use compareTo.
if (bookList.get(in).getTitle().compareTo(bookList.get(in + 1).getTitle()) < 0) { ...
If s1 and s2 are strings, s1.compareTo(s2) returns a negative value if s1 is lexicographically less than s2, a positive value if s1 is greater, and 0 if the two strings are equal.
For your class Book make it implement Comparable. You'll have to create some methods in your Book class in order to compile. Implement them according to the Java API then you can just throw them into a TreeSet<Book> and it will be sorted.
Edit:
I realize this doesn't directly answer your question, but it would be a more Java solution.
I think change your code :
if (bookList.get(in).getRating() < bookList.get(in + 1).getRating())
to
if (bookList.get(in).getTitle().compareTo(bookList.get(in + 1).getTitle()<0)
would be OK.
But,why dont you implement different Comparators and use it like this: Collections.sort(bookList,yourComparator)
something like this:
public static void main(String[] args) {
List<Book> bookList = new ArrayList<Book>();
Collections.sort(bookList, new TitleComparator());
Collections.sort(bookList, new RatingComparator());
}
static class TitleComparator implements Comparator<Book> {
#Override
public int compare(Book o1, Book o2) {
return o1.getTitle().compareTo(o2.getTitle());
}
}
static class RatingComparator implements Comparator<Book> {
#Override
public int compare(Book o1, Book o2) {
return o1.getRating() - o2.getRating();
}
}
To implement bubble-sort for any type of Object, in that case Book, implements in your object class the interface Comparable and override the methode compareTo to define your desired handling.
The method should return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
As stated in the javadoc :
http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html
In your case, the compareto method is already implemented in the String class so you can directly use it on the book's title.
Your validation would then look like this :
if (bookList.get(in).getTitle().compareTo(bookList.get(in + 1).getTitle()) < 0)

Comparison of Pojo class properties

I have a class containing two properties:
public class player{
public player(String playerName,int points){
this.playerName=playerName;
this.points=points;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
private String playerName;
private int points;
}
I have arrayList class contains collection of palyer objects.
List palyers=new ArrayList();
players.add(new player("mike",2));
players.add(new player("steve",3));
players.add(new player("jhon",7));
players.add(new player("harry",5);
Here my question is how to display player names with smallest points difference.
Output:
Based on the example code i written:
Mike and steve is the output
THis way comparison should happen:
mike to steve --> 1
mike to jhon--->5
mike to harry-->3
steve to mike -->1
steve to jhon--->5
steve to harry--->3
jhon to mike-->5
jhon to steve-->4
jhon to harry--->2
harry to mike -->3
harry to steve-->2
harry to jhon -->2
Based on above comparison mike and steve should display
Any java API to compare the properties?
Using anonymous inner class, Comparator and Collections.sort():
Collections.sort(palyers, new Comparator(){
public int compare(Object o1, Object o2){
player p1 = (player) o1;
player p2 = (player) o2;
return p1.getPoints().compareTo(p2.getPoints());
}
});.
So you want to know the pair of players whose score has the smallest difference?
I don't think there's an API function for that, although there might be something in the Apache Commons Collections.
Otherwise you'll have to use a nested loop.
int res1 = -1, res2 = -1;
int maxDiff = Integer.MAX_VALUE;
for ( int i = 0; i < players.size( ); i++ )
{
for ( int j = i + 1; j < players.size() ; j++ )
{
int diff = Math.abs( players.get(i).getPoints( ) - players.get(j).getPoints( ) );
if ( diff < maxDiff )
{
maxDiff = diff;
res1 = i;
res2 = j;
}
}
}
System.out.println(players.get(res1).getPlayerName( ) + " and " + players.get(res2).getPlayerName( ));
Obviously, this code needs some work; for example, if two pairs of players have the same difference between them, only the latest pair processed will be reported. You may also want to re-work this piece of code to remove the default values (Note how the System.out.println will crash if your List contains 0 players, for example). I leave these for you to solve. HTH.
Write a Comparator and use it to sort the List by points. You're just comparing Player instances.
Yes, implement Comparable with your player class (please use "Player", uppercase first letter for classes, otherwise it's confusing):
public class Player implements Comparable<Player>
{
....
public int compareTo(Player other)
{
if (this.points == other.points)
return 0;
if (this.points > other.points)
return 1;
return -1;
}
}
Then you can sort the List using Collections.sort(players);

Sorting using Comparator- Descending order (User defined classes) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to sort my objects in descending order using comparator.
class Person {
private int age;
}
Here I want to sort a array of Person objects.
How can I do this?
You can do the descending sort of a user-defined class this way overriding the compare() method,
Collections.sort(unsortedList,new Comparator<Person>() {
#Override
public int compare(Person a, Person b) {
return b.getName().compareTo(a.getName());
}
});
Or by using Collection.reverse() to sort descending as user Prince mentioned in his comment.
And you can do the ascending sort like this,
Collections.sort(unsortedList,new Comparator<Person>() {
#Override
public int compare(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
});
Replace the above code with a Lambda expression(Java 8 onwards) we get concise:
Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));
As of Java 8, List has sort() method which takes Comparator as parameter(more concise) :
personList.sort((a,b)->b.getName().compareTo(a.getName()));
Here a and b are inferred as Person type by lambda expression.
For whats its worth here is my standard answer. The only thing new here is that is uses the Collections.reverseOrder(). Plus it puts all suggestions into one example:
/*
** Use the Collections API to sort a List for you.
**
** When your class has a "natural" sort order you can implement
** the Comparable interface.
**
** You can use an alternate sort order when you implement
** a Comparator for your class.
*/
import java.util.*;
public class Person implements Comparable<Person>
{
String name;
int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name + " : " + age;
}
/*
** Implement the natural order for this class
*/
public int compareTo(Person p)
{
return getName().compareTo(p.getName());
}
static class AgeComparator implements Comparator<Person>
{
public int compare(Person p1, Person p2)
{
int age1 = p1.getAge();
int age2 = p2.getAge();
if (age1 == age2)
return 0;
else if (age1 > age2)
return 1;
else
return -1;
}
}
public static void main(String[] args)
{
List<Person> people = new ArrayList<Person>();
people.add( new Person("Homer", 38) );
people.add( new Person("Marge", 35) );
people.add( new Person("Bart", 15) );
people.add( new Person("Lisa", 13) );
// Sort by natural order
Collections.sort(people);
System.out.println("Sort by Natural order");
System.out.println("\t" + people);
// Sort by reverse natural order
Collections.sort(people, Collections.reverseOrder());
System.out.println("Sort by reverse natural order");
System.out.println("\t" + people);
// Use a Comparator to sort by age
Collections.sort(people, new Person.AgeComparator());
System.out.println("Sort using Age Comparator");
System.out.println("\t" + people);
// Use a Comparator to sort by descending age
Collections.sort(people,
Collections.reverseOrder(new Person.AgeComparator()));
System.out.println("Sort using Reverse Age Comparator");
System.out.println("\t" + people);
}
}
I would create a comparator for the person class that can be parametrized with a certain sorting behaviour. Here I can set the sorting order but it can be modified to allow sorting for other person attributes as well.
public class PersonComparator implements Comparator<Person> {
public enum SortOrder {ASCENDING, DESCENDING}
private SortOrder sortOrder;
public PersonComparator(SortOrder sortOrder) {
this.sortOrder = sortOrder;
}
#Override
public int compare(Person person1, Person person2) {
Integer age1 = person1.getAge();
Integer age2 = person2.getAge();
int compare = Math.signum(age1.compareTo(age2));
if (sortOrder == ASCENDING) {
return compare;
} else {
return compare * (-1);
}
}
}
(hope it compiles now, I have no IDE or JDK at hand, coded 'blind')
Edit
Thanks to Thomas, edited the code. I wouldn't say that the usage of Math.signum is good, performant, effective, but I'd like to keep it as a reminder, that the compareTo method can return any integer and multiplying by (-1) will fail if the implementation returns Integer.MIN_INTEGER... And I removed the setter because it's cheap enough to construct a new PersonComparator just when it's needed.
But I keep the boxing because it shows that I rely on an existing Comparable implementation. Could have done something like Comparable<Integer> age1 = new Integer(person1.getAge()); but that looked too ugly. The idea was to show a pattern which could easily be adapted to other Person attributes, like name, birthday as Date and so on.
String[] s = {"a", "x", "y"};
Arrays.sort(s, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
System.out.println(Arrays.toString(s));
-> [y, x, a]
Now you have to implement the Comparator for your Person class.
Something like (for ascending order): compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1 or Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id)).
To minimize confusion you should implement an ascending Comparator and convert it to a descending one with a wrapper (like this) new ReverseComparator<Person>(new PersonComparator()).
Using Google Collections:
class Person {
private int age;
public static Function<Person, Integer> GET_AGE =
new Function<Person, Integer> {
public Integer apply(Person p) { return p.age; }
};
}
public static void main(String[] args) {
ArrayList<Person> people;
// Populate the list...
Collections.sort(people, Ordering.natural().onResultOf(Person.GET_AGE).reverse());
}
package com.test;
import java.util.Arrays;
public class Person implements Comparable {
private int age;
private Person(int age) {
super();
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public int compareTo(Object o) {
Person other = (Person)o;
if (this == other)
return 0;
if (this.age < other.age) return 1;
else if (this.age == other.age) return 0;
else return -1;
}
public static void main(String[] args) {
Person[] arr = new Person[4];
arr[0] = new Person(50);
arr[1] = new Person(20);
arr[2] = new Person(10);
arr[3] = new Person(90);
Arrays.sort(arr);
for (int i=0; i < arr.length; i++ ) {
System.out.println(arr[i].age);
}
}
}
Here is one way of doing it.
The java.util.Collections class has a sort method that takes a list and a custom Comparator. You can define your own Comparator to sort your Person object however you like.

Categories