Storms786
Storms786

Reputation: 456

Java 8 Streams how to sum a total based on a list of strings

Using a java stream, how do i perform a conditional calculation based on a list of Strings (shopping clothes)?

So if a shirt costs 10.5 and jeans cost 9.5 then the one shirt and one jeans should cost 20

    double totalCost = 0;
    List <String> shopping = Arrays.asList("Shirt", "Jeans");
    shopping.stream()
    .forEach(string -> {
        if (string.equals("Shirt")) {
            totalCost += 10.5d;
        } else if (string.equals("Jeans")) {
            totalCost += 9.5d;
        } 
    });
    System.out.println(totalCost);

The above code doesnt even compile because it wont let me use totalCost inside the stream

Upvotes: 1

Views: 882

Answers (2)

g-t
g-t

Reputation: 1533

You really shouldn't use double. IEEE 754 is very problematic. Consider the following example:

System.out.println(0.1d + 0.2d);

Result:

0.30000000000000004

I would use BigDecimal and map of items' costs.

public static void main(String [] args) {
    final Map<String, BigDecimal> itemCosts = ImmutableMap.of(
            "Shirt", new BigDecimal("10.5"),
            "Jeans", new BigDecimal("9.5"));
    final BigDecimal sum = ImmutableList.of("Shirt", "Jeans", "Something").stream()
            .map(item -> itemCosts.getOrDefault(item, BigDecimal.ZERO))
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    System.out.println(sum);
}

Upvotes: 0

Stefan Dollase
Stefan Dollase

Reputation: 4620

You cannot modify local variables from a lambda expression. Instead, use a combination of mapToDouble and sum:

double totalCost = Arrays.asList("Shirt", "Jeans").stream().mapToDouble(string -> {
    if (string.equals("Shirt")) {
        return 10.5d;
    } else if (string.equals("Jeans")) {
        return 9.5d;
    } else {
        return 0;
    }
}).sum();
System.out.println(totalCost);

BTW: You really should not use double for money.

Upvotes: 4

Related Questions