- How to sort an IntStream in reverse order
- 4 Answers 4
- How to Reverse Array in Java
- Reverse Array Using Java 7
- Using Swapping Approach
- Using Copying Approach
- Using Collections.reverse() Method
- Array in Reverse Order Using Java 8
- Using Guava API
- Using Apache Commons Library
- Conclusion
- How to reverse the elements of a stream in Java
- You might also like.
- How to get ordered stream from a list in reverse order in Java 8
- 6 Answers 6
How to sort an IntStream in reverse order
I’m reading in numbers from a .txt file using BufferedReader . I want to reverse the order of elements in this steam so that when they are collected they will be arranged from the highest to the lowest. I don’t want to sort after the array has been built because I have no idea how many elements might be in it, I only need the highest N elements.
in = new BufferedReader(reader); int[] arr = in.lines() .mapToInt(Integer::parseInt) .sorted() .limit((long) N) .toArray();
If you know you won’t have any Integer.MIN_VALUE values, you can add a step to map i -> (-i) . (The Integer.MIN_VALUE qualification is important, since Integer.MIN_VALUE == (- Integer.MIN_VALUE) ).
Also, do you know if the sort-limit combo is optimized? Because if not, there’s a good chance that sorted() is anyway going to store them all in memory, in which case you may as well just get that array and read the N greatest elements.
@yshavit I think you’re right about the sort-limit combo, it has to store it in some intermediate container
It definitely has to store it in some container. The question is, is the sort step smart enough to know that there’s a limit step right after it? If so, the container could be only N-large, with each new element either getting dropped or pushing out a previously-existing element. If the stream is actually that smart, then doing something clever (as you’re asking to do) could definitely be worth it. If not, then you’re not really saving much.
4 Answers 4
Try negating the values before sorting and negating (back to normal) after sorting:
in = new BufferedReader(reader); int[] arr = in.lines() .mapToInt(Integer::parseInt) .map(i -> -i).sorted().map(i -> -i) .limit((long) N) .toArray();
Because the reverse order is not the natural order, sorted() can’t be used to sort in reverse order. If you avoid the IntStream , using a Stream instead, then you can use a Collections.reverseOrder() to sort the stream in a reverse to the natural order. Then you can call mapToInt and convert to int[] at the end.
int[] arr = in.lines() .map(Integer::valueOf) // Extract Integer, not int .sorted(Collections.reverseOrder()) // On Stream .limit(N) .mapToInt(i -> i) // map Integer to int .toArray();
when using Instream, you are actually dealing with primitive, and your hands are tight (you are limited to natural ordering and you can’t define custom comparator. You have two solutions:
- stick with the primitive stream and come up with hacks like the one proposed by @normanrz
- or you can convert to Integer (box) and use variety of solution like the one bellow (but be advised this boxing and unboxing might cause performance problems).
int[] sortedArray = IntStream.of(costs).boxed() .sorted(Collections.reverseOrder()) .mapToInt(value -> value.intValue()).toArray();
It’s hard to say whether .sorted().limit((long) N).toArray() will get optimized in some cases (it’s implementation dependent but given Oracle’s current implementation, I wouldn’t expect it), but in this special case, the source stream is a stream of unknown size which makes optimizations even less likely.
If you want to be on the safe side, you may adapt this solution for getting the n maximum numbers of a stream efficiently. All you have to do is to reverse the order:
public static IntStream maxValuesDescending(IntStream source, int limit) < TreeMapm=new TreeMap<>(Comparator.reverseOrder()); source.forEachOrdered(new IntConsumer() < int size, min=Integer.MIN_VALUE; public void accept(int value) < if(valuecount==1? null: count-1); > >); if(m.size()==limit)// no duplicates return m.keySet().stream().mapToInt(Integer::valueOf); return m.entrySet().stream().flatMapToInt(e->< int value = e.getKey(), count = e.getValue(); return count==1? IntStream.of(value): IntStream.range(0, count).map(i->value); >); >
int[] arr = maxValuesDescending(in.lines().mapToInt(Integer::parseInt), N).toArray();
But you are not required to create an array as you can use arbitrary IntStream operations on the result. This solution will hold at most N values, even less if there are duplicates as it only holds distinct values and their count.
How to Reverse Array in Java
If you are looking for how to reverse an array in Java, then this article is just written for you, keep reading until the end.
As we know, arrays are one of the most used data structures for storing multiple values in a single variable.
So, we are going to explore different ways to invert the order of an array’s values using Java core methods and external libraries.
Reverse Array Using Java 7
Java 7 provides several approaches to invert an array. Let’s go down the rabbit hole and take a close look at each approach.
Using Swapping Approach
To reverse the order of an array’s elements, we can simply use a traditional for loop.
First, we need to iterate over the given array. Then, we alternate the element at the index i with the element at the index arrayLength — i — 1 until we reach the middle of the array.
Now, let’s see how to implement this in Java:
@Test public void reverseArrayUsingSwapping() < String[] initialArray = < "A", "B", "C", "D", "E", "F" >; for (int i = 0; i < initialArray.length / 2; i++) < String temp = initialArray[i]; initialArray[i] = initialArray[initialArray.length - i - 1]; initialArray[initialArray.length - i - 1] = temp; >String[] reversedArray = < "F", "E", "D", "C", "B", "A" >; assertArrayEquals(reversedArray, initialArray); >
Using Copying Approach
Here, we will use the for loop as well, but with a different logic.
The basic idea is to use another array that acts as a copy of the initial array. However, we need to copy the elements in reverse order.
Now, let’s illustrate this using a practical example:
@Test public void reverseArrayUsingCopying() < String[] initialArray = < "A", "B", "C", "D", "E", "F" >; String[] result = new String[initialArray.length]; for (int i = 0; i < initialArray.length; i++) < result[i] = initialArray[initialArray.length - i - 1]; >String[] reversedArray = < "F", "E", "D", "C", "B", "A" >; assertArrayEquals(reversedArray, result); >
Please note that we can’t use the enhanced for loop to iterate through an array backward.
Using Collections.reverse() Method
Collections is a utility class that comes with multiple ready-to-use static methods for operating and manipulating collections.
Among these methods, we find the reverse() method. It was introduced with the aim of reversing a collection of elements.
@Test public void reverseArrayUsingCollections() < String[] initialArray = < "A", "B", "C", "D", "E", "F" >; Collections.reverse(Arrays.asList(initialArray)); String[] reversedArray = < "F", "E", "D", "C", "B", "A" >; assertArrayEquals(reversedArray, initialArray); >
Please note that the method accepts a list and not an array. This is why we used the Arrays.asList() method.
Array in Reverse Order Using Java 8
The Java 8 stream API provides another convenient way to reverse the order of the elements in a particular array.
So, let’s exemplify this using a test case:
@Test public void reverseArrayUsingStreamApi() < int[] initialArray = < 1, 9, 5, 8, 3, 2 >; int[] result = IntStream.rangeClosed(1, initialArray.length) .map(i -> initialArray[initialArray.length - i]) .toArray(); int[] reversedArray = < 2, 3, 8, 5, 9, 1 >; assertArrayEquals(reversedArray, result); >
As we can see, we used map to swap the elements. Then, we called the terminal operation toArray() to return the reversed array.
Using Guava API
Guava is a library provided by Google. It comes with a set of utility and helper classes.
For instance, it offers Lists.reverse() to return a reversed view of a given list.
Typically, the method accepts a list as a parameter. So, we need to call Arrays.asList() to pass an array:
@Test public void reverseArrayUsingGuava() < Object[] initialArray = < "A", "B", "C", "D", "E", "F" >; Object[] result = Lists.reverse(Arrays.asList(initialArray)) .toArray(); Object[] reversedArray = < "F", "E", "D", "C", "B", "A" >; assertArrayEquals(reversedArray, result); >
As shown above, since Lists.reverse() returns a list, we used the toArray() method to get the reversed elements as an array.
Using Apache Commons Library
Another solution would be using the Apache Commons Lang library.
It provides the ArrayUtils.reverse() method for inversing an array in a null-safe manner (it accepts null as a parameter).
@Test public void reverseArrayUsingApacheCommonsLang() < String[] initialArray = < "A", "B", "C", "D", "E", "F" >; ArrayUtils.reverse(initialArray); String[] reversedArray = < "F", "E", "D", "C", "B", "A" >; assertArrayEquals(reversedArray, initialArray); >
Please bear in mind that Guava and Apache Commons are external libraries, so we need to add their dependencies in pom.xml
Conclusion
To sum it up, we have covered in-depth everything you need to know about how to reverse an array in Java.
Along the way, we have seen how to use Java 7 and Java 8 methods to achieve this.
Then, we showcased how to use external libraries such as Guava and Apache Commons to accomplish the same objective.
Liked the Article? Share it on Social media!
If you enjoy reading my articles, buy me a coffee ☕. I would be very grateful if you could consider my request ✌️
How to reverse the elements of a stream in Java
Java 8 introduced the Stream API, a sequence of objects supporting sequential and parallel aggregate operations. By design, a Stream doesn’t store any data, so it is not a data structure. It also doesn’t modify the original data source.
In simple words, Java 8 streams are just wrappers around a data source like collections, arrays, or other I/O channels. The Stream API provides methods that can be chained together to produce the desired results.
In this article, you’ll learn how to reverse the elements of a stream in Java 8 and higher.
Note that this tutorial is not about sorting a stream in reverse order but simply reversing the position of the elements in the Stream .
Let us start s with a basic example:
// create a simple Stream of strings StreamString> stream = Stream.of("Alex", "John", "Baray", "Emma"); // reverse stream and print elements stream.collect(Collectors.toCollection(LinkedList::new)) .descendingIterator().forEachRemaining(System.out::println);
In the above example, we first created a Stream of string and then collect the elements into a LinkedList .
Since the LinkedList is a double-linked data structure in Java, we can iterate it in any direction: forward and backward.
We preferred to loop over the LinkedList object in the reverse direction using the descendingIterator() method. Here is what the output looks like:
✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.
You might also like.
How to get ordered stream from a list in reverse order in Java 8
Is there a sane way to get an ordered stream from a list (array list specifically, but it shouldn’t matter) that streams elements in reverse of how they are in the original list? I’m looking for a solution that doesn’t involve buffering data in anything (collector, another list, array, etc, because they copy the container which is wasteful), or uses Collections.reverse (because it modifies the list). So far, the cleanest ways that I see here is to implement my own version of Spliterator that’s ORDERED and advances through the list in reverse, or implement an Iterator that iterates in reverse, and use Spliterators.spliteratorUnknownSize(iterator,ORDERED) on it. Note this question is different from Java 8 stream reverse order : that other question asks on how to reverse a stream (which is impossible in general case), and answers offer to reverse the source somehow (which I don’t want to do), and then stream that reversed source. The cost of reversing the source is O(N), and I want to avoid it at all if possible.
6 Answers 6
If your List is a random access list, you may simply use
int num=list.size()-1; IntStream.rangeClosed(0, num).mapToObj(i->list.get(num-i))
to create a Stream which has the characteristics ORDERED | SIZED | SUBSIZED and offers full splitting support.
For a non-random access list like LinkedList it would be a performance disaster, however, who uses LinkedList anyway?
You may also check via list instanceof RandomAccess first…