How to use a Java8 lambda to sort a stream in reverse order?
You can adapt the solution you linked in How to sort ArrayList<Long> in Java in decreasing order? by wrapping it in a lambda:
.sorted((f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified())
note that f2 is the first argument of Long.compare
, not the second, so the result will be reversed.
Java8 lambda: sort a stream in reverse order?
It's a type inference issue. You'll need to help the compiler out.
few things you could try:
.sorted(comparing(T::getDailyPercentageChange).reversed())
or
.sorted(comparing((T mps) -> mps.getDailyPercentageChange()).reversed())
Where T
is the type of elements being compared.
Sort a stream descending number
You can pass the custom Comparator to sort descending order by extracting integer from every string
List<String> sortedList = list.stream()
.sorted(Comparator.<String>comparingInt(s->Integer.parseInt(s.split(":")[0].trim())).reversed())
.collect(Collectors.toList());
or you can also use Collections.sort
Collections.sort(list,Comparator.<String>comparingInt(s->Integer.parseInt(s.split(":")[0].trim())).reversed());
Reverse a comparator in Java 8
You can use Comparator.reverseOrder()
to have a comparator giving the reverse of the natural ordering.
If you want to reverse the ordering of an existing comparator, you can use Comparator.reversed()
.
Sample code:
Stream.of(1, 4, 2, 5)
.sorted(Comparator.reverseOrder());
// stream is now [5, 4, 2, 1]
Stream.of("foo", "test", "a")
.sorted(Comparator.comparingInt(String::length).reversed());
// stream is now [test, foo, a], sorted by descending length
How do I sort a Stream in reversed order with Speedment
Use the built-in comparator for the field you want to use and apply the Comparator::reversed operation like this:
films.stream()
.filter(Film.LENGTH.greaterThan(120))
.sorted(Film.LENGTH.comparator().reversed()) // <--- Here
.skip(100)
.limit(50)
.collect(Collectors.toList());
Java 8 stream reverse order
For the specific question of generating a reverse IntStream
, try something like this:
static IntStream revRange(int from, int to) {
return IntStream.range(from, to)
.map(i -> to - i + from - 1);
}
This avoids boxing and sorting.
For the general question of how to reverse a stream of any type, I don't know of there's a "proper" way. There are a couple ways I can think of. Both end up storing the stream elements. I don't know of a way to reverse a stream without storing the elements.
This first way stores the elements into an array and reads them out to a stream in reverse order. Note that since we don't know the runtime type of the stream elements, we can't type the array properly, requiring an unchecked cast.
@SuppressWarnings("unchecked")
static <T> Stream<T> reverse(Stream<T> input) {
Object[] temp = input.toArray();
return (Stream<T>) IntStream.range(0, temp.length)
.mapToObj(i -> temp[temp.length - i - 1]);
}
Another technique uses collectors to accumulate the items into a reversed list. This does lots of insertions at the front of ArrayList
objects, so there's lots of copying going on.
Stream<T> input = ... ;
List<T> output =
input.collect(ArrayList::new,
(list, e) -> list.add(0, e),
(list1, list2) -> list1.addAll(0, list2));
It's probably possible to write a much more efficient reversing collector using some kind of customized data structure.
UPDATE 2016-01-29
Since this question has gotten a bit of attention recently, I figure I should update my answer to solve the problem with inserting at the front of ArrayList
. This will be horribly inefficient with a large number of elements, requiring O(N^2) copying.
It's preferable to use an ArrayDeque
instead, which efficiently supports insertion at the front. A small wrinkle is that we can't use the three-arg form of Stream.collect()
; it requires the contents of the second arg be merged into the first arg, and there's no "add-all-at-front" bulk operation on Deque
. Instead, we use addAll()
to append the contents of the first arg to the end of the second, and then we return the second. This requires using the Collector.of()
factory method.
The complete code is this:
Deque<String> output =
input.collect(Collector.of(
ArrayDeque::new,
(deq, t) -> deq.addFirst(t),
(d1, d2) -> { d2.addAll(d1); return d2; }));
The result is a Deque
instead of a List
, but that shouldn't be much of an issue, as it can easily be iterated or streamed in the now-reversed order.
How to define custom sorted comparator in java 8 Stream to compare on the key and the value
You are looking for a custom Comparator
such as this:
.sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue()) == 0 ?
o1.getKey().compareTo(o2.getKey()) : o2.getValue().compareTo(o1.getValue()))
Theoretically,
compare the values first in descending order
o2.getValue().compareTo(o1.getValue())
andif they are equal compare the keys in the ascending order
o1.getKey().compareTo(o2.getKey())
.
Related Topics
Utf-8 Charset Doesn't Work with Javax.Mail
How to Use Concurrentlinkedqueue
How to Load an Org.W3C.Dom.Document from Xml in a String
Find Files in a Folder Using Java
How to Call Super Constructor in Lombok
Simplest Way to Print an 'Intstream' as a 'String'
How to Split Array List into Equal Parts
How to Get the Count of Line in a File in an Efficient Way
Java Benchmarking - Why Is the Second Loop Faster
How to Add a Timeout Value When Using Java's Runtime.Exec()
When Do You Need to Explicitly Call a Superclass Constructor
In Java, How to Define an Integer Constant in Binary Format