Using Comparable for Multiple Dynamic Fields of Vo in Java

Using Comparable for multiple dynamic fields of VO in java

1)You should write two Comparator for sorting on age and name separately, and then use the Collections.sort(List,Comparator). Something like this:

class StudentVO {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

class AgeComparator implements Comparator<StudentVO> {

@Override
public int compare(StudentVO o1, StudentVO o2) {
Integer age1 = o1.getAge();
Integer age2 = o2.getAge();
return age1.compareTo(age2);
}

}

class NameComparator implements Comparator<StudentVO> {

@Override
public int compare(StudentVO o1, StudentVO o2) {
return o1.getName().compareTo(o2.getName());
}

}

And then use them, To sort based on age:

Collections.sort(list,new AgeComparator());

to sort based on name:

Collections.sort(list,new NameComparator());

2) If you think that the List of StudentVO has some natural order of sorting, say suppose sort by age. Then, use Comparable for age and Comparator for name.

 class StudentVO implements Comparable<StudentVO>{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(StudentVO o) {
return ((Integer)getAge()).compareTo(o.getAge());
}
}

class NameComparator implements Comparator<StudentVO> {

@Override
public int compare(StudentVO o1, StudentVO o2) {
return o1.getName().compareTo(o2.getName());
}

}

And then use them, To sort based on age:

Collections.sort(list);

to sort based on name:

Collections.sort(list,new NameComparator());

How to compare objects by multiple fields

You can implement a Comparator which compares two Person objects, and you can examine as many of the fields as you like. You can put in a variable in your comparator that tells it which field to compare to, although it would probably be simpler to just write multiple comparators.

Sort a List of objects by multiple fields

Your Comparator would look like this:

public class GraduationCeremonyComparator implements Comparator<GraduationCeremony> {
public int compare(GraduationCeremony o1, GraduationCeremony o2) {
int value1 = o1.campus.compareTo(o2.campus);
if (value1 == 0) {
int value2 = o1.faculty.compareTo(o2.faculty);
if (value2 == 0) {
return o1.building.compareTo(o2.building);
} else {
return value2;
}
}
return value1;
}
}

Basically it continues comparing each successive attribute of your class whenever the compared attributes so far are equal (== 0).

How can I sort a Java list using two different values?

Just add another condition to your comparator:

public int compare(LeagueTableItem o1, LeagueTableItem o2){
int diff = o2.getPoints() - o1.getPoints();
if (diff == 0) {
diff = o2.goalScored() - o1.goalScored();
}
return diff;
}

JAVA - Sort Array of Json by multiple values while preserving previous sort order

A sorting algorithm that preserves the existing order on same-valued entries is called stable. In Java, you can consult the API whether a given sorting function is guaranteed to be stable, such as Arrays.sort.

The typical way of sorting using multiple keys is to sort the entries sequentially with a stable sorting algorithm in reverse order of keys.

For example, if you want to order by first name first and last name second, you would first sort by last name and then by first name.

You also need to make sure that the data structure you use preserves the order of insertion, for example a Set or Map may not preserve that.

Sort a list of objects by two fields ascending order and descending order using comparable in Java

You can compare first DateJournal(in descending order) and after that CodeJournal(in ascending order) as given below:

@Override
public int compare(final journal j1, final journal j2) {
int res;
res = j2.getDateLivraison().compareTo(j1.getDateLivraison());
if (res == 0)
res = j1.getCodeJournal().compareTo(j2.getCodeJournal());
return res;
}

ComparisonChain for multiple ways of sorting?

A Comparable should implement exactly one way of comparing. Allowing it to be changed actually breaks the contract of Comparable, which requires that (to quote the Javadoc) sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. If you can change the comparison that individual Fruit objects use, you can have an object x that says it's greater than y, while y says it's greater than x, and so on. Imagine if you have a List<Fruit> containing objects that are each configured to use a different sort order... trying to sort that list would just be chaos and not produce anything useful.

If you want multiple alternative ways of sorting, create Comparators implementing each of those ways and expose them to users in some way. Then a single Comparator can be passed to the sort method (or TreeSet constructor, or whatever), ensuring that all comparisons use that logic.

Sort a List of Objects based on runtime property

Create a Comparator for the job:

public class EmployeeComparator implements Comparator<Employee> {

private final String type;

public EmployeeComparator (String type) {
this.type = type;
}

public int compare(Employee e1, Employee e2) {
if (type.equals("name")) {
return e1.getName().compareTo(e2.getName());
}
return e1.getId().compareTo(e2.getId());
}

}

Then to use it

String type = "name"; // determined at runtime
Collections.sort(list, new EmployeeComparator(type));

The reflective version would be similar, except you would look for a method on the object of "get" + type (capitalised) and invoke that and hard cast it to Comparable and use compareTo (I'll try to show the code, but I'm using my iPhone and its a bit of a stretch, but here goes)

public class DynamicComparator implements Comparator<Object> {
private final String type;
// pass in type capitalised, eg "Name"
// ie the getter method name minus the "get"
public DynamicComparator (String type) {
this.type = type;
}
public int compare(Object o1, Object o2) {
// try-catch omitted
Method m = o1.getClass().getMethod("get" + type);
String s1 = (String)m.invoke(o1);
String s2 = (String)m.invoke(o2);
return s1.compareTo(s2);
}
}

OK... Here's how to do it without creating a class, using an anonymous class (with exception handling so code compiles):

List<?> list;
final String attribute = "Name"; // for example. Also, this is case-sensitive
Collections.sort(list, new Comparator<Object>() {
public int compare(Object o1, Object o2) {
try {
Method m = o1.getClass().getMethod("get" + attribute);
// Assume String type. If different, you must handle each type
String s1 = (String) m.invoke(o1);
String s2 = (String) m.invoke(o2);
return s1.compareTo(s2);
// simply re-throw checked exceptions wrapped in an unchecked exception
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
});

java: How can I do dynamic casting of a variable from one type to another?

Regarding your update, the only way to solve this in Java is to write code that covers all cases with lots of if and else and instanceof expressions. What you attempt to do looks as if are used to program with dynamic languages. In static languages, what you attempt to do is almost impossible and one would probably choose a totally different approach for what you attempt to do. Static languages are just not as flexible as dynamic ones :)

Good examples of Java best practice are the answer by BalusC (ie ObjectConverter) and the answer by Andreas_D (ie Adapter) below.


That does not make sense, in

String a = (theType) 5;

the type of a is statically bound to be String so it does not make any sense to have a dynamic cast to this static type.

PS: The first line of your example could be written as Class<String> stringClass = String.class; but still, you cannot use stringClass to cast variables.



Related Topics



Leave a reply



Submit