How to Use a Java8 Lambda to Sort a Stream in Reverse Order

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()) and

  • if they are equal compare the keys in the ascending order o1.getKey().compareTo(o2.getKey()).



Related Topics



Leave a reply



Submit