How to sort IntStream in reverse order

I am reading numbers from a TXT file using BufferedReader . I want to change the order of the elements in this pair, so that when they are assembled, they will be located from the highest to the lowest. I donโ€™t want to sort after the array was built, because I have no idea how many elements can be in it, I need only the highest N elements.

 in = new BufferedReader(reader); int[] arr = in.lines() .mapToInt(Integer::parseInt) .sorted() .limit((long) N) .toArray(); 
+10
source share
5 answers

Try to cancel the values โ€‹โ€‹before sorting and negating (return 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(); 
+10
source

Since the reverse order is not a natural order, sorted() cannot be used to sort in the reverse order. If you avoid IntStream , use Stream<Integer> instead, then you can use Collections.reverseOrder() to sort the stream in reverse order in 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<Integer> .limit(N) .mapToInt(i -> i) // map Integer to int .toArray(); 
+6
source

when using Instream, you are actually dealing with a primitive, and your hands are tightly squeezed (you are limited by natural ordering and cannot define your own comparator. You have two solutions:

  • stick with primitive flow and come up with hacks like suggested by @normanrz

  • or you can convert to an integer (field) and use different solutions as shown below (but keep in mind that this boxing and unpacking can cause performance problems).

     int[] sortedArray = IntStream.of(costs).boxed() .sorted(Collections.reverseOrder()) .mapToInt(value -> value.intValue()).toArray(); 
+1
source

It is difficult to say whether .sorted().limit((long) N).toArray() will be optimized in some cases (its implementation depends, but taking into account the current Oracles implementation, I would not expect this), but in this particular case the stream The source is a stream of unknown size, which makes optimization even less likely.

If you want to be safe, you can adapt this solution to efficiently obtain n maximum stream numbers. All you have to do is reorder:

 public static IntStream maxValuesDescending(IntStream source, int limit) { TreeMap<Integer,Integer> m=new TreeMap<>(Comparator.reverseOrder()); source.forEachOrdered(new IntConsumer() { int size, min=Integer.MIN_VALUE; public void accept(int value) { if(value<min) return; m.merge(value, 1, Integer::sum); if(size<limit) size++; else m.compute(min=m.lastKey(), (k,count)->count==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); }); } 

Then you can use it as

 int[] arr = maxValuesDescending(in.lines().mapToInt(Integer::parseInt), N).toArray(); 

But you do not need to create an array, as you can use arbitrary IntStream operations for the result. This solution will contain no more than N values, even less if there are duplicates, since it contains only certain values โ€‹โ€‹and their score.

0
source

the following lambda solution should be able to compete in speed with replace () patterns
String str = "TeZxtX Xto moXYdifyX";

 BiFunction<String,String,String> deleteChars = (fromString, chars) -> { StringBuilder buf = new StringBuilder( fromString ); IntStream.range( 0, buf.length() ).forEach( i -> { while( i < buf.length() && chars.indexOf( buf.charAt( i ) ) >= 0 ) buf.deleteCharAt( i ); } ); return( buf.toString() ); }; 

deleteChars.apply( str, "XYZ" );//โ€“> Text to modify

0
source

All Articles