I've got a public List<FriendProfile> friends = new ArrayList<FriendProfile>();. I initialize the friends list by reading the information from the server. The FriendProfile object contains a int called private int userPosition;
Once the friends list has been initialized, I would like to sort the friends list by having the FriendProfile object with the highest userPosition at index 0 of the list and then sort by accordingly, index 1 with the second highest userPosition ...
I guess I could write an sorting algorithm, yet I'm looking for prewritten code (maybe the JDK has some methods to offer?)
Help is appreciated!
Use Collections.sort() and specify a Comparator:
Collections.sort(friends,
new Comparator<FriendProfile>()
{
public int compare(FriendProfile o1,
FriendProfile o2)
{
if (o1.getUserPosition() ==
o2.getUserPosition())
{
return 0;
}
else if (o1.getUserPosition() <
o2.getUserPosition())
{
return -1;
}
return 1;
}
});
or have FriendProfile implement Comparable<FriendProfile>.
Implement Comparable Interface.
class FriendProfile implements Comparable<FriendProfile> {
private int userPosition;
#Override
public int compareTo(FriendProfile o) {
if(this.userPosition > o.userPosition){
return 1;
}
return 0;
}
}
Just Call the Collection.sort(List) method.
FriendProfile f1=new FriendProfile();
f1.userPosition=1;
FriendProfile f2=new FriendProfile();
f2.userPosition=2;
List<FriendProfile> list=new ArrayList<FriendProfile>();
list.add(f2);
list.add(f1);
Collections.sort(list);
The List will be sorted.
Now no need to Boxing (i.e no need to Creating OBJECT using new Operator use valueOf insted with compareTo of Collections.Sort..)
1)For Ascending order
Collections.sort(temp, new Comparator<XYZBean>()
{
#Override
public int compare(XYZBean lhs, XYZBean rhs) {
return Integer.valueOf(lhs.getDistance()).compareTo(rhs.getDistance());
}
});
1)For Deascending order
Collections.sort(temp, new Comparator<XYZBean>()
{
#Override
public int compare(XYZBean lhs, XYZBean rhs) {
return Integer.valueOf(rhs.getDistance()).compareTo(lhs.getDistance());
}
});
Use Collections.Sort and write a custom Comparator that compares based on userPosition.
use Comparator with Collections.sort method
java.util.Collections.sort(list, new Comparator<FriendProfile >(){
public int compare(FriendProfile a, FriendProfile b){
if(a.getUserPosition() > b.getUserPosition()){
return 1;
}else if(a.getUserPosition() > b.getUserPosition()){
return -1;
}
return 0;
}
});
see this link
There are two ways to do this.
1.
FriendProfile could implement the interface Comparable.
public class FriendProfile implements Comparable<FriendProfile>
{
public int compareTo(FriendProfile that)
{
// Descending order
return that.userPosition - this.userPosition;
}
}
...
Collections.sort(friendProfiles);
2.
You could write a Comparator.
public class FriendProfileComparator implements Comparator<FriendProfile>
{
public int compare(FriendProfile fp1, FriendProfile fp2)
{
// Descending order
return fp2.userPosition - fp1.userPosition;
}
}
...
Collections.sort(friendProfiles, new FriendProfileComparator());
When comparing objects rather than primitives note that you can delegate on to the wrapper objects compareTo. e.g. return fp2.userPosition.compareTo(fp1.userPosition)
The first one is useful if the object has a natural order that you want to implement. Such as Integer implements for numeric order, String implements for alphabetical. The second is useful if you want different orders under different circumstances.
If you write a Comparator then you need to consider where to put it. Since it has no state you could write it as a Singleton, or a static method of FriendProfile.
You can use java.lang.Comparable interface if you want to sort in only One way.
But if you want to sort in more than one way, use java.util.Compartor interface.
eg:
The class whose objects are to be Sorted on its roll_nos
public class Timet {
String name;
int roll_no;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getN() {
return roll_no;
}
public void setN(int n) {
this.roll_no = n;
}
public Timet(String name, int n) {
this.name = name;
this.roll_no = n;
}
public String toString(){
return this.getName();
}
}
The class for sorting:
public class SortClass {
public void go(){
ArrayList<Timet> arr = new ArrayList<Timet>();
arr.add(new Timet("vivek",5));
arr.add(new Timet("alexander",2));
arr.add(new Timet("catherine",15));
System.out.println("Before Sorting :"+arr);
Collections.sort(arr,new SortImp());
System.out.println("After Sorting :"+arr);
}
class SortImp implements Comparator<Timet>{
#Override
public int compare(Timet t1, Timet t2) {
return new Integer(t1.getN()).compareTo (new Integer((t2.getN())));
}
}
public static void main(String[] args){
SortClass s = new SortClass();
s.go();
}
}
Related
I am trying to develop a program that can sort an array of objects that are of different class types, but in the same hierarchy as one another. All of the objects are listed within the same array that I am trying to sort, and while I can alphabetically sort an array of objects that are of the same type easily enough, I cannot figure out how to sort everything all at once with the same Arrays.sort() method. Any help that anyone could provide would be greatly appreciated.
import java.util.Arrays;
public class Driver {
public static void main(String[] args) {
Vehicle[] machines = new Vehicle[3];//Example of an array that I can sort
machines[0] = new Vehicle("Giant Robot");
machines[1] = new Vehicle("Time Machine");
machines[2] = new Vehicle("Airplane");
Arrays.sort(machines);
for (int i = 0; i < machines.length; i++)
System.out.println(machines[i].getName());
Vehicle[] vehicles = new Vehicle[7];//example of an array that I cannot sort
vehicles[0] = new Car("Batmobile", 10);
vehicles[1] = new Helicopter("Batcopter", "x");
vehicles[2] = new Car("Jaguar", 6);
vehicles[3] = new Helicopter("RC Copter", "t");
vehicles[4] = new Car("Accelerator", 6);
vehicles[5] = new Helicopter("Stormshadow", "z");
vehicles[6] = new Car("Batmobile", 11);
}
}
**
public class Vehicle implements Comparable {
private String name;
public Vehicle(){
name = "no name";
}
public Vehicle(String newName){
name = newName;
}
public String getName(){
return name;
}
public int compareTo(Object o)
{
if ((o != null) &&
(o instanceof Vehicle))
{
Vehicle otherVehicle = (Vehicle) o;
return (name.compareTo(otherVehicle.name));
}
return -1;
}
}
**
public class Car extends Vehicle {
private int tireSize;
public Car(){
super();
tireSize = 0;
}
public Car(String newName, int newTireSize){
super(newName);
tireSize = newTireSize;
}
public int getSize(){
return tireSize;
}
}
**
public class Helicopter extends Vehicle {
private String bladeType;
public Helicopter(){
super();
bladeType = "none";
}
public Helicopter(String newName, String newBlade){
super(newName);
bladeType = newBlade;
}
public String getType(){
return bladeType;
}
}
Goal: You need to be able to compare a Vehicle to other of Vehicle.
To achieve that goal:
public class Vehicle implements Comparable<? extends Vehicle> {
....
public int compareTo(Object o) {
// Now, that the Comparable is for the type Vehicle
// you know that o is some kind of vehicle
// check vehicle related things
// number of seats, dogs, whatever
return -1;
}
}
You just need to adjust your code to:
class Vehicle implements Comparable<Vehicle> {
private String name;
/* ... */
#Override
public int compareTo(Vehicle vehicle) {
return name.compareTo(vehicle.getName());
}
}
In most cases, your classes should not implement Comparable, unless there is one and only one ordering that is always the correct one, like with numbers. Your vehicles can be sorted by name, by age, and probably by more criteria, so they should not implement Comparable.
Instead, you can pass the ordering function as a lambda function, at the time where you actually sort your vehicles:
Arrays.sort(machines, (left, right) -> left.getName().compareTo(right.getName()));
Or, equivalently:
Arrays.sort(machines, Comparator.comparing(Vehicle::getName));
This way you don’t need the implements Comparable anymore.
If you want to sort by vehicle type then you need to take class type into consideration, while sorting the element. Modify the compareTo() method as shown below:
public int compareTo(Object o){
if ((o != null) &&
(o instanceof Vehicle)){
Vehicle otherVehicle = (Vehicle) o;
return (otherVehicle.getClass().getSimpleName().equals(this.getClass().getSimpleName()) ?
name.compareTo(otherVehicle.name)
: otherVehicle.getClass().getSimpleName().compareTo(this.getClass().getSimpleName()));
}
return -1;
}
I am trying to sort the elements present in my arraylist in decreasing order. However, there seems to be some issue in the implementation. I am just a beginner in java, and am trying to use the most easiest method possible to sort.
student temp = new student(user_name,given_name,family_name,tot_marks);
for(int j=0;j<list1.size()-1;j++)
{
for(int k=0;k<list1.size();k++)
{
student sort1 = list1.get(j);
student sort2 = list1.get(k);
if(sort1.tot_marks < sort2.tot_marks)
{
temp.user_name=sort1.user_name;
temp.family_name=sort1.family_name;
temp.given_name=sort1.given_name;
temp.tot_marks=sort1.tot_marks;
sort2.user_name=temp.user_name;
sort2.family_name=temp.family_name;
sort2.given_name=temp.given_name;
sort2.tot_marks=temp.tot_marks;
sort1.family_name=sort2.family_name;
sort1.given_name=sort2.given_name;
sort1.tot_marks=sort2.tot_marks;
list1.add(sort1); //Adding sorted elements to the arraylist.
}
//If marks are same, sort on the basis of username.
else if(sort1.tot_marks == sort2.tot_marks)
{
//Compare usernames whichever is greater.
{
temp.user_name=sort1.user_name;
temp.family_name=sort1.family_name;
temp.given_name=sort1.given_name;
temp.tot_marks=sort1.tot_marks;
sort2.user_name=temp.user_name;
sort2.family_name=temp.family_name;
sort2.given_name=temp.given_name;
sort2.tot_marks=temp.tot_marks;
sort1.family_name=sort2.family_name;
sort1.given_name=sort2.given_name;
sort1.given_name=sort2.given_name;
sort1.tot_marks=sort2.tot_marks;
list1.add(sort1);
}
}
}
}
//Print the sorted list.
for (int i=0;i<list1.size();i++)
{
student display = list1.get(i);
System.out.println(display.tot_marks+","+display.given_name+"
"+display.family_name);
}
You could just do:
Collections.sort(list1, new Comparator<student>() {
#Override
public int compare(student one, student another) {
if (one.tot_marks == another.tot_marks) {
return 0;
}
return one.tot_marks > another.tot_marks ? 1 : -1;
}
});
However a few advices:
Class names like student are not very easy for the eye for java developers. Try using capitalized camel case class names (in this case Student)
Underscores in member names are also not very nice in java, try camel case names (totMarks). Even better is a geter, and setter for it, rather than leaving it public. (getTotMarks(), setTotMarks(int))
Also before doing something like you did, try researching a bit! There is a good chance, somebody else wrote it before you!
In java to sort a List you should use Collections.sort and a Comparator.
Collections.sort(list1, new Comparator<student>() {
public int compare(student a, student b) {
if(a.tot_marks < b.tot_marks)
return -1;
else if (a.tot_marks > b.tot_marks)
return 1;
else
return a.username.compareTo(b.username);
}
});
No need for that. You are adding duplicated to your list.
list1.add(sort1); //Adding sorted elements to the arraylist.
Check your swap logic. It should be:
TEMP = SORT1
SORT1 = SORT2
SORT2 = TEMP
The way to go is to ditch your approach and make your student class implement the Comparable interface: public class student implements Comparable<student>. Also, in Java, class names should start with upper case letters.
Once that you make your class implement this interface, you will be forced to implement the compareTo(student student) method.
In this method, you will implement your comparison logic:
public int compareTo(student student)
{
if(this.marks != student.marks)
{
return Integer.compare(this.marks, student.marks);
}
else
{
return this.name.compareTo(student.name);
}
}
Then, to sort your array, simply call like so:
List<student> students = ...
Collections.sort(students);
The above will call your implementation of the .compareTo and sort the array accordingly.
To Sort the arrayList in descending order please implement the Comparator interface
and as Denis rightly pointed out.Do not duplicate the elements
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MyArrayListSort {
public static void main(String a[]){
List<Student> list = new ArrayList<Student>();
list.add(new Student("Ram",3000));
list.add(new Student("John",6000));
list.add(new Student("Crish",2000));
list.add(new Student("Tom",2400));
Collections.sort(list,new MyMarkComp());
System.out.println("Sorted list entries: ");
for(Student e:list){
System.out.println(e);
}
}
}
class MyMarkComp implements Comparator{
#Override
public int compare(Student e1, Student e2) {
if(e1.getMarks() < e2.getMarks()){
return 1;
} else {
return -1;
}
}
}
class Student{
private String name;
private int mark;
public Student(String n, int s){
this.name = n;
this.salary = s;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMarks() {
return mark;
}
public void setMarks(int mark) {
this.mark = mark;
}
public String toString(){
return "Name: "+this.name+"-- Marks: "+this.mark;
}
}
Say I have arraylist A and to compare 2 objects of A I do a.getDistanceFromPlayer() < b.getDistanceFromPlayer().
I want to now have list B which will have all of A's objects, but sorted where the first object is closest to player, and last object is furthest.
What might be the fastest way to do this?
Thanks
Have A implement Comparable and then define the method compareTo(Object other) like so:
public int compareTo(Object other) {
if( this.getDistanceFromPlayer() < other.getDistanceFromPlayer() ) {
return -1;
} else if( this.getDistanceFromPlayer() > other.getDistanceFromPlayer()) {
return 1;
}
return 0;
}
Now you can call Collections.sort() on your list of objects
Use Collections.sort with a custom comparator.
eg.
public class DistanceComparator implements Comparator<Integer>{
#Override
public int compare(YourObject o1, YourObject o2) {
if (o1.getDistanceFromPlayer() > o2.getDistanceFromPlayer())
{
return 1;
}
else if (o1.getDistanceFromPlayer() < o2.getDistanceFromPlayer())
{
return -1;
}
return 0;
}
}
Then in your program, call
Collections.sort(YourArrayInstance, new DistanceComparator())
You should make your class implement Comparable.
Then you can use Collections.sort() to sort your List.
If you want a sorted List AND an unsorted List, you'll have to make a copy.
Another option is to create a Comparator.
If you read the documentation for Collections, you'll see it has two sort methods.
One bases the sort on the objects' compareTo method (ie their "natural order").
The other bases the sort on a Comparator that is passed as the second argument.
Here's a link to another question that provides an example implementation of Comparable:
Example implementation of Comparable
Use a Custom Comparator :
B = Collections.sort(A, new CustomComparator());
public class CustomComparator implements Comparator<ClassA> {
#Override
public int compare(final ClassA a, final ClassA b) {
//Make sure you check that neither a nor b are null..
//..
if (a.getDistanceFromPlayer() < b.getDistanceFromPlayer()) {
return 1;
} else if (a.getDistanceFromPlayer() > b.getDistanceFromPlayer()) {
return -1;
}
return 0;
}
}
You can use a custom Comparator and sort your ArrayList, like this:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Main {
public static class Player {
private final float distance;
public Player (final float position) {
this.distance = position;
}
public float getDistanceFrom () {
return distance;
}
#Override
public String toString() {
return "Player [distance=" + distance + "]";
}
}
public static void main(String[] args) throws Exception {
final ArrayList<Player> players = new ArrayList<Player> ();
players.add (new Player (2));
players.add (new Player (5));
players.add (new Player (-3));
players.add (new Player (1));
Collections.sort(players, new Comparator<Player> () {
#Override
public int compare(Player o1, Player o2) {
final float distance1 = o1.getDistanceFrom();
final float distance2 = o2.getDistanceFrom();
return (int) Math.signum (distance1 - distance2);
}
});
System.out.println(players);
}
}
And a fiddle for it.
suppose, I have a student class with roll number and name. I want to sort it out wrt roll number. I tried the following .Here is my code:
package CollectionDemo;
import java.util.*;
class student1 implements Comparable<student1>{
int rollNo;
String name;
student1(int rollNo,String name){
this.rollNo=rollNo;
this.name=name;
}
#Override
public boolean equals(Object o){
if((o instanceof student1) && (((student1)o).rollNo == rollNo)){
return true;
}
else
{
return false;
}
}
#Override
public int hashCode(){
return 1;
}
public int compareTo(student1 s) {
return s.rollNo;
}
public String toString(){
return "["+rollNo+","+name+"]";
}
}
public class treeSetDemo {
public static void main(String... a){
Set<student1> set=new TreeSet<student1>();
set.add(new student1(102,"Anu"));
set.add(new student1(101,"Tanu"));
set.add(new student1(103,"Minu"));
System.out.println("elements:"+set);
}
}
o/p: elements:[[102,Anu], [101,Tanu], [103,Minu]]
so, its not sorting:( how to make it correct .
thanks for your help.
================================================
thanks for all your help. The following code runs fine, but now I want to know how it works, if i comment out equals and hashcode method.
package CollectionDemo;
import java.util.*;
class student1 implements Comparable<student1>{
int rollNo;
String name;
student1(int rollNo,String name){
this.rollNo=rollNo;
this.name=name;
}
/* #Override
public boolean equals(Object o){
if((o instanceof student1) && (((student1)o).rollNo == rollNo)){
return true;
}
else
{
return false;
}
}
#Override
public int hashCode(){
return 1;
}
*/
public int compareTo(student1 s) {
System.out.println("hello:"+(this.rollNo-s.rollNo));
return this.rollNo-s.rollNo;
}
public String toString(){
return "["+rollNo+","+name+"]";
}
}
public class treeSetDemo {
public static void main(String... a){
Set<student1> set=new TreeSet<student1>();
set.add(new student1(102,"Anu"));
set.add(new student1(101,"Tanu"));
set.add(new student1(103,"Minu"));
System.out.println("elements:"+set);
}
}
OP:
run:
hello:-1
hello:1
elements:[[101,Tanu], [102,Anu], [103,Minu]]
BUILD SUCCESSFUL (total time: 0 seconds)
you have to change compareTo method in bellow way
public int compareTo(student1 s) {
if(s.rollNo == this.rollNo){
return 0;
}else if(s.rollNo > this.rollNo){
return -1;
}else{
return 1;
}
}
- If you want to sort on the basis of only one attribute, then go with java.lang.Comparable<T> Intereface, along with Collections.sort(List l).
- But if you aim is to sort it on the basis of more then one attribute then go for java.util.Comparator<T> along with Collections.sort(List l, Comparator c).
Eg:
import java.util.Comparator;
public class Fruit implements Comparable<Fruit>{
private String fruitName;
private String fruitDesc;
private int quantity;
public Fruit(String fruitName, String fruitDesc, int quantity) {
super();
this.fruitName = fruitName;
this.fruitDesc = fruitDesc;
this.quantity = quantity;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
public String getFruitDesc() {
return fruitDesc;
}
public void setFruitDesc(String fruitDesc) {
this.fruitDesc = fruitDesc;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int compareTo(Fruit compareFruit) {
int compareQuantity = ((Fruit) compareFruit).getQuantity();
//ascending order
return this.quantity - compareQuantity;
//descending order
//return compareQuantity - this.quantity;
}
public static Comparator<Fruit> FruitNameComparator
= new Comparator<Fruit>() {
public int compare(Fruit fruit1, Fruit fruit2) {
String fruitName1 = fruit1.getFruitName().toUpperCase();
String fruitName2 = fruit2.getFruitName().toUpperCase();
//ascending order
return fruitName1.compareTo(fruitName2);
//descending order
//return fruitName2.compareTo(fruitName1);
}
};
}
I think this implementation is close to recommended:
#Override
public int compareTo(Object other) {
if(other == null || !(other instanceOf student)){
throw new IllegalArgumentException();
}
student s = (student) other;
if(this.rollNo > s.rollNo){
return 1;
} else if (this.rollNo < s.rollNo){
return -1;
} else {
return 0;
}
}
If you are using Comparable interface then your compareTo() method should return the comparison not equals method , Google comparable example.
Check this link
In your compareTo method, you are just returning the value of the object you are comparing to. You need to return the difference, of the attribute of the invoking instance and passed instance.
So, change your compareTo method to the below one: -
#Override
public int compareTo(student1 s) {
return this.rollNo - s.rollNo;
}
NOTE: - Only sign is important for Collections.sort, so you don't really need an if-else block to return -1, 0, or 1. Just return the difference. That's all.
P.S : -
Your hashcode implementation is a very poor one. It will put every instances in the same bucket.
#Override
public int hashCode(){
return 1; // All the instances will have the same hashcode.
}
Ideally, you should use only those attributes to calculate the hashCode which you have used to compare your two instances, here its rollNo.
So, rather than returning simply a value 1, you can have some equations, that calculates your hashcode, taking into to consideration your rollNo and a large prime number also.
You can go through Effective Java - Item#9 for more explanation of this topic.
Now, that your code is working fine, lets move to your 2nd doubt.
equals and hashCode methods are not used when you want to compare two objects that will be used while sorting. We override equals and hashCode methods in order to check whether an instance is equal to another instance later on.
So, compareTo method is not concerned with whether you have ocerrided equals ad hashCode method or not. And you can also infer from name as to what the two methods does, and can they be related or not.
Moreover, equals method is defined in Object class, whereas compareTo method is declared in Comparable interface. So, they are not interrelated.
Check the documentation of these methods: - Object#equals, Object#hashCode, and Comparable#compareTo
I have this class:
public class Friend {
private String name;
private String location;
private String temp;
private String humidity;
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
I want to sort a List based on name, location, temp and humidity based on user input.
EDIT:The user specifies by which data member the sorting has to be done.
What is the easiest way to do this?
Thank you.
Because you want to sort them by four different standards, implementing Comparable does not make sense. In this case, you may find that creating different Comparators for each sort-by parameter. However, you could implement Comparable for the most logical sort-by field, such as name. Otherwise, comparators are the way to go.
public class FriendNameComparator extends Comparator<Friend> {
// assuming both are non-null for code simplicity; you may wish to change that
public int compare(Friend f1, Friend f2) {
return f1.getName().compareTo(f2.getName());
}
}
public class FriendLocationComparator extends Comparator<Friend> {
// assuming both are non-null for code simplicity; you may wish to change that
public int compare(Friend f1, Friend f2) {
return f1.getLocation().compareTo(f2.getLocation());
}
}
// and so forth
Then, you can use the sort function of the Collections utility class to sort by the given comparator.
Collections.sort(friendsList, new FriendNameComparator()); // sorts by name
Collections.sort(friendsList, new FriendLocationComparator()); // sorts by location
// etc
Java has a static function called Collections.sort(List, Comparator) which sorts a (generified) List of objects given a custom Comparator which, given two objects of the same type, determines which one is ordered before the other.
Your task is to write a function which creates a Comparator which orders the objects based on its arguments and the user specified sort order. For example:
public Comparator<Friend> getComparator(final String sortBy) {
if ("name".equals(sortBy)) {
return new Comparator<Friend>() {
#Override int compare(Friend f1, Friend f2)
return f1.getName().compareTo(f2.getName());
}
};
} else if ("location".equals(sortBy)) {
return new Comparator<Friend>() {
#Override int compare(Friend f1, Friend f2)
return f1.getLocation().compareTo(f2.getLocation());
}
};
} else if ("temp".equals(sortBy)) {
// ...
} else {
throw new IllegalArgumentException("invalid sort field '" + sortBy + "'");
}
}
List list=new ArrayList();
Use If else if for each criteria:
if(location ){
Collections.sort(list, new Comparator () {
public int compare(YourObject o1, YourObject o2) {
return o1.getLocation().compareTo(o2.getLocation());
}
});
}
} else if(temp ){
........
}
.......