I'm interested in sorting an list of object based on date attribute in that object. I can either use list sort method.
list.sort( (a, b) -> a.getDate().compareTo(b.getDate()) );
Or I can use stream sorted method
List<E> l = list.stream()
.sorted( (a, b) -> a.getDate().compareTo(b.getDate()))
.collect(Collectors.toList());
Out of both above option which should we use and why?
I know the former one will update my original list and later one will not update the original but instead give me a fresh new list object.
So, I don't care my original list is getting updated or not. So which one is good option and why?
If you wish to known which is best, your best option is to benchmark it: you may reuse my answer JMH test.
It should be noted that:
List::sort
useArrays::sort
. It create an array before sorting. It does not exists for otherCollection
.Stream::sorted
is done as state full intermediate operation. This means theStream
need to remember its state.
Without benchmarking, I'd say that:
- You should use
collection.sort()
. It is easier to read:collection.stream().sorted().collect(toList())
is way to long to read and unless you format your code well, you might have an headache (I exaggerate) before understanding that this line is simply sorting. sort()
on aStream
should be called:- if you filter many elements making the
Stream
effectively smaller in size than the collection (sorting N items then filtering N items is not the same than filtering N items then sorting K items with K <= N). - if you have a map transformation after the sort and you loose a way to sort using the original key.
- if you filter many elements making the
If you use your stream with other intermediate operation, then sort
might be required / useful:
collection.stream() // Stream<U> #0
.filter(...) // Stream<U> #1
.sorted() // Stream<U> #2
.map(...) // Stream<V> #3
.collect(toList()) // List<V> sorted by U.
;
In that example, the filter apply before the sort: the stream #1 is smaller than #0, so the cost of sorting with stream might be less than Collections.sort().
If all that you do is simply filtering, you may also use a TreeSet
or a collectingAndThen
operation:
collection.stream() // Stream<U> #0
.filter(...) // Stream<U> #1
.collect(toCollection(TreeSet::new))
;
Or:
collection.stream() // Stream<U>
.filter(...) // Stream<U>
.collect(collectingAndThen(toList(), list -> {
list.sort();
return list;
})); // List<V>