Reputation: 142
I have tried this
List<Integer> numbers = Arrays.asList(1, 1, 0, -1, -1);
List<Integer> positiveNum2 = new ArrayList<>();
List<Integer> negativeNum2 = new ArrayList<>();
List<Integer> zeroNumbers2 = new ArrayList<>();
List<Integer> positiveNumbers = numbers.stream().filter(number -> number > 0).collect(Collectors.toList());
List<Integer> negativeNumbers = numbers.stream().filter(number -> number < 0).collect(Collectors.toList());
List<Integer> zeroNumbers = numbers.stream().filter(number -> number.equals(0)).collect(Collectors.toList());
positiveNumbers.forEach(System.out::println);
negativeNumbers.forEach(System.out::println);
zeroNumbers.forEach(System.out::println);
System.out.println("*********with Consumer******************");
Consumer<Integer> determineNumber = number -> {
if (number > 0) {
positiveNum2.add(number);
} else if (number < 0) {
negativeNum2.add(number);
} else {
zeroNumbers2.add(number);
}
};
numbers.forEach(determineNumber);
positiveNum2.forEach(System.out::println);
negativeNum2.forEach(System.out::println);
zeroNumbers2.forEach(System.out::println);
but I dont know which one is better, I think the forEach with the Consumer, but the Consumer does three validations, therefore, does not have single responsability
Upvotes: 3
Views: 1260
Reputation: 4555
I would generally prefer your Consumer
based solution as it at least encapsulates the whole operation in one call/stream. But I think you don't yet take full advantage of the functional approach of streams.
You could use a simple stream/collect to achieve this sorting:
numbers .stream()
.collect(Collectors.groupingBy(Math::signum));
will result in a map like this:
{1.0=[1], 0.0=[0, 0], -1.0=[-1, -2, -1]}
This approach avoids side effects (i.e. does not modify lists outside of the stream's scope) and can hence be extracted more easily and is easily run in parallel.
Upvotes: 1
Reputation: 97237
The consumer only takes one iteration, so it's more efficient, and it does have a single responsibility: dividing the numbers over three lists based on their sign.
For this case, I'd probably use a simple for
loop though.
If you really want to over-engineer things, you can define an enum
to represent the sign, and use a grouping collector to group into a map:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static java.util.stream.Collectors.groupingBy;
public class Test {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 1, 0, -1, -1);
Map<Sign, List<Integer>> map = numbers
.stream()
.collect(groupingBy(i -> i > 0
? Sign.POSITIVE
: i < 0
? Sign.NEGATIVE
: Sign.ZERO));
System.out.println(map);
}
}
enum Sign {POSITIVE, NEGATIVE, ZERO}
This yields the following output:
{ZERO=[0], POSITIVE=[1, 1], NEGATIVE=[-1, -1]}
Note: If you want peak performance for future lookups in your map, you can use an EnumMap
instead. Take a look at this answer to see how.
Upvotes: 0