Sorting a Collection of Objects

Sorting a collection of objects

Implement the Comparator interface (once for each different sort order) and use the Collections.sort() method that takes a Comparator as additional parameter.

How to sort a Collection of Objects?

Collections.sort

Collections.sort(List<T> list) sorts the specified list into ascending order, according to the natural ordering of its elements.

For example:

List<String> fruits = new ArrayList<String>();

fruits.add("Pineapple");
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Banana");

Collections.sort(fruits);

int i=0;
for(String temp: fruits){
System.out.println("fruits " + ++i + " : " + temp);
}

Will give as output:

fruits 1 : Apple
fruits 2 : Banana
fruits 3 : Orange
fruits 4 : Pineapple

See other examples at: Java object sorting example (Comparable and Comparator).

Comparator

Comparator is a comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order.

Collections.sort(people, new Comparator<Person>() {

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

Lambda Expressions

Java 8 introduced Lambda Expressions and the Comparator's equivalent is:

Comparator<Person> people =
(Person o1, Person o2)->o1.getLastName().compareTo(o2.getLastName());

How to sort a Collection of objects based on 2 properties

Use Java 8 methods of the Comparator interface comparing() and thenComparing():

Comparator<Transactions> byTypeAndTo = 
Comparator.comparing(Transactions::getType)
.thenComparing(Transactions::getTo);

In order to sort a list of objects, you can apply method sort() on it, available since Java 8:

transactions.sort(byTypeAndTo);

You can play around with this Online demo.

For more information on how to build comparators using Java 8, have a look at this tutorial.

But the last line of code gives an error:

The method signature is incorrect, I believe it should be:

public void processTransactions(Collection<Transactions> ts)

Don't confuse utility class Collections with the Collection interface, and don't omit the generic type parameter.

You can invoke method sort() only on the object of type List (the same with Collections.sort() it expects a list and comparator).

In order to sort the list provided in the guise of Collection you need to apply casting. Since you have a requirement that you method should expect an argument of type Collection there's no other way around it (but it's not good design). That's how it might look like:

public void processTransactions(Collection<Transactions> ts) {
if (!(ts instanceof List<Transactions>)) {
throw new IllegalArgumentException();
}
List<Transactions> transactions = (List<Transactions>) tr;

transactions.sort(byTypeAndTo);

// process the `transactions` list
}

Note: it's better to define a comparator inside the Bank class as a public static final field.

Sort a Java collection object based on one field in it

here is my "1liner":

Collections.sort(agentDtoList, new Comparator<AgentSummaryDTO>(){
public int compare(AgentSummaryDTO o1, AgentSummaryDTO o2){
return o1.getCustomerCount() - o2.getCustomerCount();
}
});

UPDATE for Java 8:
For int datatype

 Collections.sort(agentDtoList, (o1, o2) -> o1.getCustomerCount() - o2.getCustomerCount());

or even:

 Collections.sort(agentDtoList, Comparator.comparing(AgentSummaryDTO::getCustomerCount));

For String datatype (as in comment)

Collections.sort(list, (o1, o2) -> (o1.getAgentName().compareTo(o2.getAgentName())));

..it expects getter AgentSummaryDTO.getCustomerCount()

Sorting object property by values

Move them to an array, sort that array, and then use that array for your purposes. Here's a solution:

let maxSpeed = {
car: 300,
bike: 60,
motorbike: 200,
airplane: 1000,
helicopter: 400,
rocket: 8 * 60 * 60
};
let sortable = [];
for (var vehicle in maxSpeed) {
sortable.push([vehicle, maxSpeed[vehicle]]);
}

sortable.sort(function(a, b) {
return a[1] - b[1];
});

// [["bike", 60], ["motorbike", 200], ["car", 300],
// ["helicopter", 400], ["airplane", 1000], ["rocket", 28800]]

Once you have the array, you could rebuild the object from the array in the order you like, thus achieving exactly what you set out to do. That would work in all the browsers I know of, but it would be dependent on an implementation quirk, and could break at any time. You should never make assumptions about the order of elements in a JavaScript object.

let objSorted = {}
sortable.forEach(function(item){
objSorted[item[0]]=item[1]
})

In ES8, you can use Object.entries() to convert the object into an array:

const maxSpeed = {
car: 300,
bike: 60,
motorbike: 200,
airplane: 1000,
helicopter: 400,
rocket: 8 * 60 * 60
};

const sortable = Object.entries(maxSpeed)
.sort(([,a],[,b]) => a-b)
.reduce((r, [k, v]) => ({ ...r, [k]: v }), {});

console.log(sortable);

How to natural-sort a collection of objects in JavaScript?

Ascending and Descending order

const arr = [{name: "John", size: "100"},{name: "John", size: "80"},{name: "John", size: "82"},{name: "John", size: "110"},{name: "John", size: "70"},{name: "John", size: "M"},{name: "John", size: "S"},{name: "John", size: "XS"},{name: "John", size: "L"},{name: "John", size: "XL"}],

handler = (a, b, desc) => {

if (isNaN(+a) && isNaN(+b)) return (desc ? b.localeCompare(a) : a.localeCompare(b));

else if (!isNaN(+a) && !isNaN(+b)) return (desc ? (+b - +a) : (+a - +b));

else if (isNaN(+a)) return (desc ? -1 : 1);

else return (desc ? 1 : -1);

},

descending = arr.sort(({size: a}, {size: b}) => handler(a, b, true)),

ascending = [...arr].sort(({size: a}, {size: b}) => handler(a, b));

console.log("Ascending")

console.log(ascending);

console.log("Descending")

console.log(descending);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sorting a collection of objects in Java where implementing class is final

You can implement your own Comparator without extending the class, and use it as a parameter for Collections.sort:

public class MyComparator implements Comparator<MyClass> {
@Override
int compate (MyClass a, MyClass b) {
// null handling removed for clarity's sake
// add it if you need it
return a.getName().compareTo(b.getName());
}
}

And now just use it:

List<MyClass> myList = ...;
Collections.sort (myList, new MyComparator());

Java 8 - sort a Collection of Objects by a property with an order defined in an array

You can use Arrays.asList(names).indexOf(f.getName()) as comparison key:

List<String> nameList = Arrays.asList(names);
List<Foo> fooList = new ArrayList<>(fooCollection);
fooList.sort(Comparator.comparingInt(f -> nameList.indexOf(f.getName())));

Or if you definitely want Stream API:

List<Foo> fooList = fooCollection.stream()
.sorted(Comparator.comparingInt(f -> nameList.indexOf(f.getName())))
.collect(Collectors.toList());

However if you have many names, you may consider making this more efficient, preparing first a reverse index of names:

Map<String, Integer> nameMap = IntStream.range(0, names.length)
.boxed()
.collect(Collectors.toMap(idx -> names[idx], Function.identity()));
List<Foo> fooList = fooCollection.stream()
.sorted(Comparator.comparing(f -> nameMap.get(f.getName())))
.collect(Collectors.toList());

Here I assume that all the names are different and every Foo has the corresponding name in the names array.



Related Topics



Leave a reply



Submit