Comparison of Pojo class properties - java

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

Related

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)

Using compareTo and Collections.sort

I have a franchise class with owner(owner of franchise's name), state(2-character string for the state where the franchise is located), and sales (total sales for the day)
public class Franchise implements Comparable <Franchise> {
final String owner;
final String state;
final double sales;
protected Franchise(String owner, String state, double sales ) {
this.owner = owner;
this.state = state;
this.sales = sales;
}
public String toString() {
String str = state + ", " + sales + ", " + owner;
return str;
}
public String getState() {
return state;
}
public double getSales() {
return sales;
}
public int compareTo(Franchise that) {
double thatSales = that.getSales();
if (this.getState().compareTo(that.getState()) < 0)
return -1;
else if (this.getSales() > thatSales)
return -1;
else if (this.getSales() < thatSales)
return 1;
else
return 0;
}
}
the compareTo is based on state ASCENDING and sales DESCENDING
import java.util.ArrayList;
import java.util.Collections;
public class FranchiseTester {
public static void main(String[] args) {
ArrayList<Franchise> franchises = new ArrayList<Franchise>();
Franchise a = new Franchise("Andrew Luck", "IN", 1270.5);
Franchise b = new Franchise("Ray Rice", "MD", 1210);
Franchise c = new Franchise("Alfred Morris", "WA", 980.5);
Franchise d = new Franchise("Roddy White", "GA", 670);
Franchise e = new Franchise("Greg Olsen", "SC", 740);
Franchise f = new Franchise("T.Y. Hilton", "IN", 950);
Franchise g = new Franchise("Julio Jones", "GA", 560);
franchises.add(a);
franchises.add(b);
franchises.add(c);
franchises.add(d);
franchises.add(e);
franchises.add(f);
franchises.add(g);
Collections.sort(franchises);
for(int i = 0; i < franchises.size(); i++) {
System.out.print(franchises.get(i) + "\n");
}
}
}
when I compare these franchise objects without the Collections.sort they compare correctly, However when I test using the Collections.sort like I have here I get an output like this:
GA, 670.0, Roddy White
GA, 560.0, Julio Jones
IN, 1270.5, Andrew Luck
IN, 950.0, T.Y. Hilton
MD, 1210.0, Ray Rice
SC, 740.0, Greg Olsen
WA, 980.5, Alfred Morris
The state's are still being compared correctly but it's not comparing by sales properly (lower sales for particular stat should come first)
I think that the .sort compares string by default is the reason that states are still correct, my question is how do I implement it to compare based on sales too?
In your problem statement you are saying that "compareTo is based on state ASCENDING and sales DESCENDING". Based on this your results are valid. States are in ascending order and for each state the sale is in descending order. In the very next statement you are saying (lower sales for particular stat should come first). So basically you have two conflicting requirement. Both can not be done simultaneously.
In other words do you want your program to do something else like both should be ascending or both descending or some other order. If yes then you have to modify your compareTo method accordingly.
You have to modify your compareTo method. Cause you are returning after comparing the state. So you have to compare state but sales too.
For example:
public int compareTo(Franchise that) {
int stateComparition = this.getState().compareTo(that.getState());
Double sales = Double.valueOf(this.getSales());
Double thatSales = Double.valueOf(that.getSales());
int salesComparition = sales.compareTo(thatSales);
if(stateComparition == 0){
if(salesComparition > 0)
return -1;
else if(salesComparition < 0)
return 1;
else
return 0;
}
return stateComparition;
}
It is because at first comparision condition you are comparing on the basis of state. If the state of current object is not small, then only comparision based on sales will take place. According to your code, in state you want the state of current object to be less than the comparing state, however in sales comparision you want the sales of current object to be greater than the comparing object. This is why you are getting different results. States are being compared in ascending order and sales in descending order. It is all dependent on what you return from compareTo function.
public int compareTo(Franchise that) {
double thatSales = that.getSales();
if (this.getState().compareTo(that.getState()) < 0)
return -1;
else if (this.getSales() < thatSales)
return -1;
else if (this.getSales() > thatSales)
return 1;
else
return 0;
}
Hope this code will help you. You can find good explanation over here
Comparable will give only one way of comparision. This can be done using Comparator interface too.
Collections.sort(list, new Comparator<Franchise>() {
#Override
public int compare(Franchise obj1, Franchise obj2) {
if(obj1.getState().compareTo(obj2.getState()) == 0)
{
Double a1 =obj1.getSales();
Double a2 = obj2.getSales();
return a2.compareTo(a1);
}
return obj1.getName().compareTo(obj2.getName());
}
}

How to sort Arraylist of objects

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.

How to sort three arrays in java?

I have three arrays in my proggramme Surname, Forename and result and need to create a sort array
Surname: Chris Forename: Charleton: Result: 54
Surname: Annett: forename: Lyle: result 67
If I wanted to sort it by alphabetical of last name, i need all the fields to move, instead of just the surname. This is the bubble sort code i'm working off
int swap;
boolean swapflag = true;
//outer loop
while (swapflag == true)
{
swapflag = false;
//inner loop
for (int index=0; index < (nums.length - 1); index++)
{
//swap routine
if (nums[index]> nums[index + 1])
{ //swap routine
swap = nums[index];
nums[index] = nums[index + 1];
nums[index + 1] = swap;
swapflag = true;
}
}//end inner
}//end outer
System.out.println ("\nArray Contents after sorting"
+ "\n*************");
for (int index=0; index < nums.length; index ++)
{
System.out.println("Array element "
+ index + ": " + nums[index]);
}
}
}
` package projStudent;
import java.util.Scanner;
public class UnitResults
{
//delcare Scanner as keyb
static Scanner keyb = new Scanner (System.in);
//declare fields
static String studentForename [];
static String studentSurname [];
static int [] studentResult;
static int pointer;
//constructor
UnitResults(int sizeofclass)
{//start of constructor
studentForename = new String [sizeofclass];
studentSurname = new String [sizeofclass];
studentResult = new int [sizeofclass];
pointer = 0;
}//end of constructor
public boolean add(String studentForename[], String studentSurname[],
int studentResult[])
{//start of add method
if (pointer == studentResult.length )
{//start of if statement
System.out.println("Sorry Array is full");
return false;
studentResult[pointer] = studentResult[];
pointer ++;
}//end of if statement
}//end of add method
public boolean delete(int element)
{//start of delete method
element = element - 1;
if ((element >= 0) && ( element < pointer))
{//start of if statement
for(int index = (element + 1); index < pointer; index++)
{//start of for statement
studentResult[index - 1] = studentResult[index];
}//end of for statement
pointer--;
return true;
}//end of if statement
else
{//start of else statement
return false;
}//end of else statement
}//end of delete method
public String find()
{//start of display
String strOutput="";
strOutput = strOutput + "Students";
if (pointer==0)
{//start of if statement
strOutput = strOutput + "There are no records in this Array";
return strOutput;
}//end of if statement
for (int index=0; index < pointer; index++)
{//start of for method
strOutput = strOutput + "Student Name" + studentSurname[index] + studentForename +
"Student Result" + studentResult +"\n";
}//end of for method
return strOutput;
}//display
public int sort (int UnitResults)
{//start of sort
int sort;
boolean swapflag = true;
while (swapflag == true)
{//start of while loop
swapflag = false;
for (int index=0; index < (UnitResults - 1); index++)
{
if (studentResult[index]> studentResult[index + 1])
{ //swap routine
sort = studentResult[index];
studentResult[index] = studentResult[index + 1];
studentResult[index + 1] = sort;
swapflag = true;
}
}
}//end of while loop
}//end of sort
}`
Unfortunately, your post is confusing as you don't include some things, like just what is the current array you are sorting. Still, if I understand your question correctly...
Regardless of the language, your strategy would involve changes to how you swap the elements. If your array consists of composite data, then simply assigning in a swap is fine. If your data is scattered, then your swap needs to swap each variable. You can always just sort the indices of the array into another array, then use that array to indirectly reference the first, for sorted access.
I would suggest you use an List for this purpose.
First create an object. For example "Person" containing members for "Forname","Surename","Result". Then fill the list with these objects, implement the Interface Compareable and use the Collection.sort() methode.
class Person implements Comparable<Person>
{
private String forname;
private String surname;
private int rating;
public Person(String forename, String surname, int rating)
{
this.forname = forename;
this.surname = surname;
this.rating = rating
}
public int compareTo(Person p) {
if(p.rating == this.rating)
return 0;
else if(p.rating < this.rating)
return -1;
return 1;
}
}
class Test{
public static void main(String[] args){
List<Person> personList = new ArrayList<Person>();
Person p1 = new Person("John","Smith",10);
Person p2 = new Person("Max","Muster",20);
Person p3 = new Person("Sarah","Clark",15);
personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.sort();
}
}
There are a number of features of the Java programming languages that can help you resolve the problem that you are having, the first of which is inclusion of appropriate data structures and methods with which to manipulate objects within those data structures.
First and foremost, I'd recommend using a java class to represent a single person entity... think about it, when you look up a person's information, you don't consult three separate books, or computer screens, or what have you, when all that information can be organized into one place. For your person above, for example, you could use something like this:
public class Person implements Comparable<Person> {
public String firstName;
public String lastName;
public int result;
public Person(String fn, String ln, int r) {
firstName = fn;
lastName = ln;
result = r;
}
public int compareTo(Person otherPerson) {
return lastName.compareTo(otherPerson.lastName);
}
}
This will give you an object that will store all of your person information, and by default will be easily sortable by last name (you can change this behavior with a comparator, which I won't cover here.)
Now instead of having three different arrays of first names, last names, and results, you can have a single array of Persons. There ARE actually sorting mechanisms within the java language for arrays already, which you can research and use if you choose, but if you'd like to use your own sort, you would just need to replace your swap conditional with something like this:
if(persons[index].compareTo(persons[index+1]) > 0) {
...
}
i just want ask you
why instead creating class student ie
class Student{
private String studentForename;
private String studentSurname;
private int studentResult;
//setters and getters
}
and put them in some collection ie List
you are putting them into 3 different arrays?
do you realize, if you have them nicely in the list, you can sort them just by using Collections.sort() ?
Can't understand properly the question: are you looking for a way to manually implement a sorting algorithm (bubble, quick or whatever) or you would like to simply sort them the best you can? Generally speaking you should never implement your own sort 'cause Java provides itself a very efficient lot... or is this an exercise? Probably :)
Best way I can imagine is, provided the 3 arrays in their original form are linked by index, create a surname/index map, load it form surname array, sort the Map.Entry by key and then you will have the array indexes sorted the way you wanted. Check here for more details: how to sort Map values by key in Java
PS The solutions provided by the others are correct and preferrable if you are NOT doing an exercise :) Better deal with a structured object than with 3 separated data.

Sort an ArrayList of Objects by last name, then first name

I have an arrayList of different types of players based on sports. I need to sort the list of players in the arrayList by last name to start. If 2 players have the same last name it needs to then sort those 2 players by the first name.
example: Format Lastname firstname
Williams Robert
Phillips Warren
Doe John
Phillips Mark
Output should be
Doe John
Phillips Mark
Phillips Warren
Williams Robert
What I have now only sorts by either the first or last. I have it by last atm in my code.
public static void sortPlayers(ArrayList playerList) {
for (int i = 0; i < playerList.size(); i++) {
for (int j = 0; j < playerList.size(); j++) {
Collections.sort(playerList, new Comparator() {
public int compare(Object o1, Object o2) {
PlayerStats p1 = (PlayerStats) o1;
PlayerStats p2 = (PlayerStats) o2;
return p1.getPlayerLastName().compareToIgnoreCase(p2.getPlayerLastName());
}
});
}
}
}
Change the comparator to:
public int compare(Object o1, Object o2) {
PlayerStats p1 = (PlayerStats) o1;
PlayerStats p2 = (PlayerStats) o2;
int res = p1.getPlayerLastName().compareToIgnoreCase(p2.getPlayerLastName());
if (res != 0)
return res;
return p1.getPlayerFirstName().compareToIgnoreCase(p2.getPlayerFirstName())
}
Petar's answer is correct, just two remarks:
Use List instead of ArrayList as method argument, as the interface is more general, and the method will work even if you change to another List type (like LinkedList... ) later
Use generics to make your code more type safe.
An improved version:
//the place where you define the List
List<PlayerStats> playerList = new ArrayList<PlayerStats>();
public static void sortPlayers(List<PlayerStats> playerList) {
Collections.sort(playerList, new Comparator<PlayerStats>() {
public int compare(PlayerStats p1, PlayerStats p2) {
int res = p1.getPlayerLastName().compareToIgnoreCase(p2.getPlayerLastName());
if (res != 0)
return res;
return p1.getPlayerFirstName().compareToIgnoreCase(p2.getPlayerFirstName())
}
});
}
Using java8 there is easy way to do this:
public List<PlayerStats> getSortedPlayerList(List<PlayerStats> playerList) {
return playerList.stream().sorted(Comparator.comparing(PlayerStats::getPlayerLastName).thenComparing(PlayerStats::getPlayerFirstName)).collect(Collectors.toList());
}
//requires java#8
//class Person { String fName; String lName; int id}
List<Person> list = new ArrayList<>();
Person p1 = new Person();
p1.setfName("a");
p1.setlName("x");
list.add(p1 );
Person p4 = new Person();
p4.setfName("b");
p4.setlName("z");
list.add(p4);
Person p3 = new Person();
p3.setfName("a");
p3.setlName("z");
list.add(p3);
Person p2 = new Person();
p2.setfName("a");
p2.setlName("y");
list.add(p2);
//sort by a single field
Collections.sort(list, (o1,o2) -> o1.getfName().compareTo(o2.getfName()));
//sort by multiple cascading comparator.
Collections.sort(list, Comparator.comparing(Person::getfName).thenComparing(Person::getlName));
list.forEach( System.out::println);
//output
//Person [fName=a, lName=x, id=null]
//Person [fName=a, lName=y, id=null]
//Person [fName=a, lName=z, id=null]
//Person [fName=b, lName=z, id=null]

Categories