1

I want to optimize following code:

List<Integer> numbers = Arrays.asList(5, 3, 2, 8);
// sorted Array of all numbers>2
        Arrays.asList(sortWithCondition(numbers, i -> i > 2)).forEach(
                data -> System.out.println("MM=" + data));



public static Integer[] sortWithCondition(List<Integer> numbers,
Predicate<Integer> predicate) {
    IntStream intStream = numbers.parallelStream().filter(predicate)
                    .mapToInt(i -> i).sorted();

            Object[] objArray = intStream.boxed().collect(Collectors.toList())
                    .toArray();

            Integer[] intArray = new Integer[objArray.length];
            for (int j = 0; j < intArray.length; j++) {
                intArray[j] = (Integer) objArray[j];
            }
            return intArray;
        }
}

Output: MM=3 MM=5 MM=8

I want to sort number if particular condition satisfied.

How to convert Stream<Integer> to Integer[] directly? and

How to convert IntStream to Integer[] directly?

AskQ
  • 4,215
  • 7
  • 34
  • 61
  • Possible duplicate of [How to Convert a Java 8 Stream to an Array?](https://stackoverflow.com/questions/23079003/how-to-convert-a-java-8-stream-to-an-array) – Seelenvirtuose Mar 09 '18 at 08:02
  • 1
    Even if you have to copy an array to get a different type, you can simply use, e.g. `Arrays.copyOf(objArray, objArray.length, Integer[].class)` to get `Integer[]`. But your entire code bears several unnecessary steps. You can replace the entire method with `return .toArray(Integer[]::new);`; forget about parallel stream, your list is way too small to get an advantage from parallel processing. Or replace the entire code with `numbers.stream().filter(predicate).sorted().forEachOrdered(data -> System.out.println("MM=" + data));` – Holger Mar 09 '18 at 08:21
  • can you post code for this algorithm assuming list is large – AskQ Mar 09 '18 at 08:25
  • You can just replace `stream()` with `parallelStream()`. You may try both and measure to find out whether there is a benefit. – Holger Mar 09 '18 at 08:26
  • @Seelenvirtuose I'm looking for minimal code which can avoid these conversions. – AskQ Mar 09 '18 at 08:32
  • Thanks @Holger for help. This is proper way: numbers.stream() .filter(i->i>2) .sorted() .forEachOrdered(data -> System.out.println("MM=" + data)) – AskQ Mar 09 '18 at 08:47
  • @AskQ change stream to `parallelStream()` and see your results time. – Adesh Kumar Mar 09 '18 at 16:41

2 Answers2

3

Note the when you have to copy an array to get a different type, you can simply use, e.g. Arrays.copyOf(objArray, objArray.length, Integer[].class) to get Integer[]. That’s just for the case you will need it in the future, as here, you don’t need it as you can simply call .toArray(Integer[]::new) on the stream to get the right array in the first place.

But since your subsequent processing step is to do Arrays.asList(…).forEach(data -> System.out.println("MM=" + data)); on the result, there is no need to collect the data at all. Apply the action to the stream elements in the first place:

numbers.stream()
       .filter(i -> i > 2)
       .sorted()
       .forEachOrdered(data -> System.out.println("MM=" + data));

This also omits the unboxing and re-boxing steps.

This doesn’t use a parallel stream, your list is way too small to get an advantage from parallel processing and for such simple tasks you usually need a really large list to get a benefit. But you may replace stream() with parallelStream() at any time and try and measure to find out whether there is a benefit.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • As it related to optimisation. what's the problem in using parallelStream here? – Adesh Kumar Mar 09 '18 at 16:40
  • @AdeshKumar parallel processing always incurs an overhead for splitting the work, sending tasks to other threads (which might even have to be started first) and to join and assemble the result. You need a sufficiently large workload truly running in parallel, to get a benefit that compensates (in the best case: overcompensates) the overhead. For small workloads, the disadvantages will dominate. – Holger Mar 12 '18 at 08:23
2

How to convert Stream to Integer[] directly?

stream.toArray(Integer[]::new);

How to convert IntStream to Integer[] directly?

intstream.boxed().toArray(Integer[]::new);

However, rethink your use of Integer[]. If you are dealing with boxed type, might as well put them in a List<Integer> and if you going with arrays, it is better to use a primitive array int[]

Misha
  • 27,433
  • 6
  • 62
  • 78
  • …and if the OP is only going to chain `.forEach(data -> System.out.println("MM=" + data))` to it, neither, `List` nor array, are really necessary, just chaining `.forEachOrdered(data -> System.out.println("MM=" + data))` to the stream would be enough. – Holger Mar 09 '18 at 08:23