Order Set<Object> by attribute String - java

I want to sort a Set<TailleDetail> by one of its string attributes (mesure), but the only solutions I saw in the internet (TreeSet and Comparator) don't work, can you help me?
My class:
public class TailleDetail {
private Integer id;
private String sexe;
private String mesure;
private Taille Taille;
}
EDIT -
For TreeSet I just try this:
Set<TailleDetail> tailles = new TreeSet<TailleDetail>();
to remplace :
Set<TailleDetail> tailles = new HashSet<TailleDetail>();
And For Comparator I try this :
Set<TailleDetail> tailles = new HashSet<TailleDetail>();
Comparator<TailleDetail> comparatorTaille = new Comparator<TailleDetail>() {
#Override
public int compare(TailleDetail left, TailleDetail right) {
return left.toString().compareToIgnoreCase(right.toString());
}
};
List<TailleDetail> tai = tailleDetailViewManager.search(param, true);
Collections.sort(tai, comparatorTaille);
tailles = new HashSet<TailleDetail>(tai);

The following code should make the trick :
final Set tailleDetails = new TreeSet(new TailleDetailComparator());
tailleDetails.add(...);
public class TailleDetailComparator implements Comparator {
#Override
public int compare(final TailleDetail o1, final TailleDetail o2) {
return o1.mesure.compareTo(o2.mesure);
}
}
Note that comparison is going to be done using the string comparison rules (alphabetically).

You're comparator does not compare by mesure, but by it's toString() method.
You should adapt your comparator to sort by mesure.
You List is already sorted, so why use a set ?
List<TailleDetail> tai = tailleDetailViewManager.search(param, true);
Collections.sort(tai, (td1, td2) -> td1.getMesure().compareTo(td2.getMesure())); // tai will be sorted by mesure
If you do want to use a Set, use a TreeSet:
SortedSet<TailleDetail> set = new TreeSet<>((td1, td2) -> td1.getMesure().compareTo(td2.getMesure())); // also sorted by mesure
set.addAll(list)
Also see When should a class be Comparable and/or Comparator?

Related

Class method that sort a list of objects with a comparator given as parameter (Java)

I´m having troubles to define a method that sort a list of the same class where is defined this method.
For example the class is defined with the following attributes:
public abstract class Licence {
//other attributes
protected List<People> myList;
//Constructor and other methods
//The method I want
public List<People> getPeopleInOrder ( Comparator c)
List<People> aux = new ArrayList<People>(this.myList);
Collections.sort(aux, c);
return aux;
And also I have this class
class CompPeople implements Comparator<People>{
public int compare( People e1, People e2) {
// Declaration the criteria of comparison
if ( c1 == 0) {
if (c2 == 0 ) return c3;
else return c2;
}
else return c1;
}
}
But when I call in main method
List<People> myNewList = Mylicence.getPeopleInOrder(new CompPeople());
EDIT: Before I was trying to sort a unmodifiable list, I changed it and now it gives me empty list.
I know I can use the method sort of Collections but what I want is a method of class Licence that sort its list with a given comparator. Thanks in advance
I think you have incorrect comparator.
Let define a People class:
public class People {
private String name;
private String city;
}
In case you plan to use different ways to compare these object, then it is better to use custom comparators. E.g. this is two comparators that sort people by one of the field. I recommend to define different comparators as part of People class:
public class People {
private String name;
private String city;
public static final Comparator<People> SORT_BY_NAME_ASC = (one, two) -> one.name.compareToIgnoreCase(two.name);
public static final Comparator<People> SORT_BY_CITY_ASC = (one, two) -> one.city.compareToIgnoreCase(two.city);
}
Now you can use it sort List<People> peoples:
people.sort(People.SORT_BY_NAME_ASC); // sort by name asc
people.sort(People.SORT_BY_CITY_ASC); // sort by city asc
people.sort(People.SORT_BY_NAME_ASC.thenComparing(People.SORT_BY_CITY_ASC)); // sort by name and city asc
You method getPeopleInOrder() could look like this:
public List<People> getPeopleInOrder(Comparator<People> comparator) {
if(myList.isEmpty())
return Collections.emptyList();
List<People> aux = new ArrayList<>(myList);
aux.sort(comparator);
return aux;
}
...or using Streams like this:
public List<People> getPeopleInOrder(Comparator<People> comparator) {
return myList.stream().sorted(comparator).collect(Collectors.toList());
}
In case you want only one comparator, then you have two ways.
class People implements Comparable
class People implements Comparable<People> {
private String name;
private String city;
#Override
public int compareTo(People people) {
int res = name.compareToIgnoreCase(people.name);
res = res == 0 ? city.compareToIgnoreCase(people.city) : res;
// compare other fields you want
return res;
}
}
Use single Comparator
public class People {
private String name;
private String city;
public static final Comparator<People> SORTY_BY_NAME_AND_CITY = (one, two) -> {
int res = one.name.compareToIgnoreCase(two.name);
res = res == 0 ? one.city.compareToIgnoreCase(two.city) : res;
// compare other fields you want
return res;
};
}
As you should be able to guess from the comment, the problem is the unmodifiableList(). For a copy, just create a new List.
public List<People> getPeopleInOrder ( Comparator c)
List<People> aux = new ArrayList<>(this.myList);
Collections.sort(aux, c);
return aux;
}

Sort a list of Comparables using multiple string fields in a custom order

With this class:
public class MyClass implements Comparable<MyClass> {
private String status;
private String name;
private String firstName;
#Override
public int compareTo(MyClass o) {
return 0;
}
}
I'd like to sort a list of MyClass objects with this order:
Firstly, status = "open", then "working" then, "close"
Secondly, name = "toto", then "titi"
Finally, firstName = "tutu", "tata"
How can I do this with the Comparable interface ?
I would do this like so: first define a set of lists which define the order for each field:
private static List<String> statusOrder = Arrays.asList("open", "working", "close");
private static List<String> nameOrder = Arrays.asList("toto", "titi");
private static List<String> firstNameOrder = Arrays.asList("tutu", "tata");
Then use List.indexOf to get the position of the element in the list, and then simply subtract the results:
#Override
public int compareTo(MyClass o) {
final int statusComp = statusOrder.indexOf(status) - statusOrder.indexOf(o.status);
if (statusComp != 0) return statusComp;
final int nameComp = nameOrder.indexOf(name) - nameOrder.indexOf(o.name);
if (nameComp != 0) return nameComp;
return firstNameOrder.indexOf(firstName) - firstNameOrder.indexOf(o.firstName);
}
The issue with this approach is that indexOf will return -1 if the element is not in the list. You would need to define the behaviour in the case where MyClass contains non-standard values (perhaps it will never happen).

How to sort Hashset<> by field?

I have a Set<MultiAdminComponent> rootItems = new HashSet<>();HashSet.
In this I have all my Screen.
In my HashSet I am going to have all my rows. I want to sort the MultiAdminComponent based on rowId.
This is MultiAdminComponent
public class MultiAdminComponent {
private String componentName;
private String componentIdentification;
private String componentType;
private String componentState;
private String componentUrl;
private String componentId;
private String rowId;
private List<MultiAdminComponent> items;
private int componentStateId;
private int ctastatus;
private String actionId;
private String actionToPerform;
private int orderNumber;
private int ctarevision;
How can I sort based on RowId in MultiAdminComponent bean
Since you are on Java 8, you can leverage Stream API and Comparator.comparing() for this:
List<MultiAdminComponent> sortedList = rootItems.stream()
.sorted(Comparator.comparing(MultiAdminComponent::getRowId))
.collect(Collectors.toList()); // collect to whatever you want
Keep in mind that HashSet does not maintain order so you should keep the sorted result in some other data structure.
And remember that this is not going to sort your Set this is going to return a List of naturally sorted MultiAdminComponents and you need to capture the result of this operation.
Just to let you know, there are few more Sets.
HashSet is not ordered/sorted
LinkedHashSet sorted by the order that it's been inserted
TreeSet sorted in natural order
I know the question been answered, but truly I can't see a point of using a HashSet which is not ordered and then try to order it when you can just use a TreeSet?
Before Java 1.8 version, which can help you
public class Test {
public static void main(String[] args) {
MultiAdminComponent m1 = new MultiAdminComponent("1");
MultiAdminComponent m2 = new MultiAdminComponent("2");
MultiAdminComponent m3 = new MultiAdminComponent("3");
Set<MultiAdminComponent> set = new HashSet<MultiAdminComponent>();
set.add(m1);
set.add(m3);
set.add(m2);
List<MultiAdminComponent> list = new ArrayList<MultiAdminComponent>(set);
for (MultiAdminComponent m : list) {
System.out.println("before" + m.getRowId());
}
Collections.sort(list, new Comparator<MultiAdminComponent>() {
#Override
public int compare(MultiAdminComponent m1, MultiAdminComponent m2) {
return m1.getRowId().compareTo(m2.getRowId());
}
});
for (MultiAdminComponent m : list) {
System.out.println("after" + m.getRowId());
}
}
}
class MultiAdminComponent {
private String rowId;
public MultiAdminComponent(String rowId) {
super();
this.rowId = rowId;
}
public String getRowId() {
return rowId;
}
public void setRowId(String rowId) {
this.rowId = rowId;
}
}

How to sort a Java list of objects using a RuleBasedCollator on a field?

I want to sort an ArrayList of objects on a specific field using a given RuleBasedCollator.
For example, we have a list of Thing objects:
public Thing {
public String name;
public String type;
}
List<Thing> things = new ArrayList<Thing>();
RuleBasedCollator ruleBasedCollator = new RuleBasedCollator("< Table < Plate < Fork < Knife");
Now, after having created Thing objects and added them to the things list, I want to sort this list, getting first things of type "table" and last things of type "knife".
Does anyone know how to do it?
You can try something like this, instead of using compareTo in compare method of Comparator you can call RuleBasedCollator's compare.
mQueue.sort((o1, o2) -> {
if (o1.getDescription().getTitle() != null && o2.getDescription().getTitle() != null) {
return mRuleBasedCollator.compare(o1.getDescription().getTitle().toString(),
o2.getDescription().getTitle().toString());
} else {
return 0;
}
});
As far as I understand a RuleBaseCollator is intended for sorting Strings, at least i says so in the Collator class which is the super class. I would instead use a Comparator, something like this:
public class ThingSorter {
public enum ThingType{
//wanted sort order, sort on ordinal :
//Table < Plate < Fork < Knife
TABLE, PLATE, FORK, KNIFE
}
public static class Thing {
private String name;
private ThingType type;
public Thing(String name, ThingType tt) {
this.name = name;
type = tt;
}
public String toString() {
return name + " [" + type + "]";
}
}
public static class MyThingComparator implements Comparator<Thing> {
#Override
public int compare(Thing t1, Thing t2) {
return t1.type.ordinal() - t2.type.ordinal();
}
}
public static class MyReverseThingComparator implements Comparator<Thing> {
#Override
public int compare(Thing t1, Thing t2) {
return t2.type.ordinal() - t1.type.ordinal();
}
}
public static void main(String[] args) throws ParseException {
List<Thing> things = new ArrayList<Thing>();
things.add(new Thing("One", ThingType.KNIFE));
things.add(new Thing("Two", ThingType.FORK));
things.add(new Thing("Three", ThingType.PLATE));
things.add(new Thing("Four", ThingType.TABLE));
System.out.println("unsorted:\n" + things);
Collections.sort(things, new MyThingComparable());
System.out.println("sorted:\n" + things);
Collections.sort(things, new MyReverseThingComparable());
System.out.println("sorted:\n" + things);
}
}
The names are are not involved in the sorting in this case just the type (and the ordinal in the type)
You could certainly use the TreeMap or enum as the previous answers suggest; a rather simpler alternative is to use just a custom compatator, without the enum. If you're using Java 8 you can get it down to a single line:
Collections.sort(things,
(Thing t1, Thing t2)->ruleBasedCollator.compare(t1.type, t2.type) );
The pre-8 version would do the same thing with an anonymous Comparator
I finally found a solution using a TreeMap. I use the "type" property for the key and a list of Thing for the value. Instead of using a RuleBasedCollator, I created a ListBasedCollator extending Collator, because RuleBasedCollator rules work on characters but not on words.
public class ListBasedCollator extends Collator {
private List<String> list;
public ListBasedCollator(String[] array) {
list = Arrays.asList(array);
}
#Override
public int compare(String source, String target) {
if(!list.contains(target)) {
return 1;
}
if(!list.contains(source)) {
return -1;
}
return Integer.valueOf(list.indexOf(source)).compareTo(Integer.valueOf(list.indexOf(target)));
}
#Override
public CollationKey getCollationKey(String source) {
return null;
}
#Override
public int hashCode() {
return 0;
}
}
Here is how I construct the TreeMap:
String[] sortingList = {"TABLE", "PLATE", "FORK", "KNIFE"};
ListBasedCollator listBasedCollator = new ListBasedCollator(sortingList);
Map<String, List<Thing>> thingMap = new TreeMap<String, List<Thing>>(listBasedCollator);
So, the thingMap will always be sorted by type using the listBasedCollator.
And I can also sort alphabetically the list of things for each different type.

How to sort a list of structs by an element of the struct in java

I have a list of structs that I would like to sort according to a specific element of the struct:
private class myStruct {
public Boolean GUI;
public float CallTime;
public String ReqID;
public String ReqGUID;
public String Stereotype;
public String StereotypeGUID;
}
private List<myStruct> DataList = new ArrayList<myStruct>();
How could I sort DataList by the element "ReqID" without hardcoding it?
Is there a possibility to use Arrays.sort()?
You should use a Comparator.
class YourComparator implements Comparator<myStruct>{
public int compare(myStruct s1, myStruct s2){
//here comes the comparison logic
}
}
And then use this form of the sort() method:
Arrays.sort(T[] arrayToSort, Comparator<T> yourComparator);
It's not very clear whether you use a collection or an array as the data structure.
In case you use a List, then use Collections.sort().
For custom sorting you can implement the Comparable interface.
With this interface you create a method compareTo() which returns a negative number, 0 or a positive number. Based on the return code Collections.sort() can tell if the element has to be before or after another element.
A nice example how to use it can be found in this answer: java class implements comparable
use the Comparator interface like this
public static void main(String[] args) {
List<myStruct> DataList = new ArrayList<myStruct>();
//ADD Objects to DataList here
Collections.sort(DataList, new Comparator() {
public int compare(Object o1, Object o2) {
myStruct p1 = (myStruct) o1;
myStruct p2 = (myStruct) o2;
int ret = -1;
//business logic here
if (Integer.parseInt(p1.ReqGUID) == Integer.parseInt(p2.ReqGUID)) {
ret = 0;
} else if (Integer.parseInt(p1.ReqGUID) > Integer.parseInt(p2.ReqGUID)) {
ret = 1;
} else if (Integer.parseInt(p1.ReqGUID) < Integer.parseInt(p2.ReqGUID)) {
ret = -1;
}//end business logic
return ret;
}
});
}
Here inside the Collections.sort() method I am implementing the Comparator interface and overriding the compare() method. This will actually sort your list based on the business logic you implemented inside the compare() method;
Your class structure look strange to me.. You have public fields inside a private class..
Ideally your fields should be marked private and you can have getters and setters to access them..
As for your problem, you can take a look at two important interfaces taht are defined for this kind of job: - http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html and http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Comparable.html..
You use Comparator when you want to have multiple ways to compare your class instance..
You can just create a class implementing the Comparator interface, and pass the instance of this class to Collections.sort() method to use this Comparator for sorting..
In this case, compare() method is used to do the job of comparison.
Alternatively, you can associate only one way of comparing a class instance by making that class implementing Comparable interface.. In this case you need to override compareTo() method..
Here's a sample code using Comparator: -
public class MyComparator implements Comparator<Box> {
#Override
public int compare(Box box0, Box box1) {
int w0 = box0.getWeight();
int w1 = box1.getWeight();
return (w0 > w1? -1 : (w0 == w1) ? 0 : 1);
}
}
public class Box {
private int weight;
public Box() {
}
public Box(int weight) {
this.weight = weight;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
And Your Main
public class Main {
public static void main(String args[]) {
List<Box> boxList = new ArrayList<Box>();
Collections.sort(boxList, new MyComparator());
}
}
Hope it helps..
You can define your own Comparator and use Collections.sort(), passing that Comparator in. That way you can define different comparators for searching using different fields.
Alternatively your struct can implement the Comparable interface and Collections.sort() can sort using this. This is called using the natural sort order, since it's implicit to your class.
Here's the Java tutorial on sorting and ordering.
Use java.util.Collections.sort() with a Comparator instance. See the JavaDocs.
Use Arrays.sort(T[] a, Comparator<? super T> c)
or Collections.sort(List a, Comparator c)
Simplest solution
Just implement java.lang.Comparable interface in you class like following:
class MyStruct implements Comparable<MyStruct>{
public Boolean GUI;
public float CallTime;
public String ReqID;
public String ReqGUID;
public String Stereotype;
public String StereotypeGUID;
#Override
public int compareTo(MyStruct other) {
return ReqID.compareTo(other.ReqID);
/* also you can use ReqID.compareToIgnoreCase(other.ReqID); */
}
#Override
public String toString() {
return "(" + ReqID + ")";
}
}
Override also toString() method just for printing.
Also, keep in mind that String's compareTo() method sorts using lexicographical order. In case you want numeric ID's it is better to use int or other numerical type.
Following is complete code to sort using Arrays.sort() as well as Collections.sort() - choose what suits you :)
public class MyStructSort {
private final static String[] STRUCT_IDS = {"C", "D", "A", "Aa", "B", "Z", "Aaa" };
private static List<MyStruct> createList() {
List<MyStruct> structList = new ArrayList<MyStruct>();
for (String id: STRUCT_IDS) {
MyStruct struct = new MyStruct();
struct.ReqID = id;
structList.add(struct);
}
return structList;
}
public static void main(String[] args) {
List<MyStruct> dataList = createList();
/* Sort using Lists (Collections) */
Collections.sort(dataList);
System.out.println("List sort:\t" + dataList);
/* Sort using arrays */
MyStruct[] dataArray = dataList.toArray(new MyStruct[dataList.size()]);
Arrays.sort(dataArray);
// print sorted array
System.out.print("Array sort:\t");
for (MyStruct struct: dataArray) {
System.out.print(struct+" ");
}
}
}
This is just demonstration code, so some null-checks and getters and setters would be needed to make it perfect.

Categories

Resources