Java 8 here. I have an array of Strings:
String[] animals = getsomehow(); // "dogs", "cats", "sheep", etc.
Then I have a map where the keys are Strings (specifically, the same literal values as some of the animals in the array above), and the values are a count (representing the number of those animals):
Map<String,Integer> animalCounts = new HashMap<String,Integer>();
animalCounts.put("sheep", 4);
animalCounts.put("dogs", 2);
animalCounts.put("cats", 0);
animalCounts.put("porcupines", null);
animalCounts.put("dolphins", 43);
I am trying to figure out how to use the Stream API to iterate over my animals array, and come up with a total number of animals. For instance, if my animals array had “sheep” and “dolphins” in it, then the total number of animals would be 4 + 43 = 47.
My best attempt so far:
int totalAnimals = Arrays.stream(animals)
    .reduce(
        0,
        (subtotal, animal) -> subtotal + animalCounts.get(animal));
However this yields a compiler error for the identity value of 0:
“Required type: String“
Can anyone spot where I’m going awry?
Advertisement
Answer
Can anyone spot where I’m going awry?
You’re using the 2-argument version of reduce:
T reduce(T identity,
         BinaryOperator<T> accumulator)
As you can see, the identity value and the output has to be of the same type as the input, so it must be String.
Solution would be to use the 3-argument version of reduce:
<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator,
             BinaryOperator<U> combiner)
As an alternative, you can do it like this:
int totalAnimals = Arrays.stream(animals)
        .map(animalCounts::get)
        .filter(Objects::nonNull)
        .mapToInt(Integer::intValue)
        .sum();