Search code examples
javajava-streambigdecimalspeedment

Bad return type in lambda expression: BigDecimal cannot be converted to long


I was trying to write a query in java stream, through speedment. When I try to sum (l_extendedprice * (1 - l_discount)) in select, I get this error:

Bad return type in lambda expression: BigDecimal cannot be converted to long. Operator '-' cannot be applied to 'int', 'java.math.BigDecimal'.

My code is this:

JoinComponent joinComponent = app.getOrThrow(JoinComponent.class);
Join<Tuple6<Customer, Orders, Lineitem, Supplier, Nation, Region>> join = joinComponent
        .from(CustomerManager.IDENTIFIER)
        .innerJoinOn(Orders.O_CUSTKEY).equal(Customer.C_CUSTKEY)
        .where(Orders.O_ORDERDATE.greaterOrEqual(sqlDate))
        .where(Orders.O_ORDERDATE.lessThan(sqlDate2))
        .innerJoinOn(Lineitem.L_ORDERKEY).equal(Orders.O_ORDERDATE)
        .innerJoinOn(Supplier.S_SUPPKEY ).equal(Customer.C_NATIONKEY)
        .innerJoinOn(Nation.N_NATIONKEY).equal(Supplier.S_NATIONKEY)
        .innerJoinOn(Region.R_REGIONKEY).equal(Nation.N_REGIONKEY)
        .where(Region.R_NAME.equal("ASIA"))
        .build(Tuples::of);

Comparator<Tuple1<String>> comparator = Comparator
        .comparing((Function<Tuple1<String>, String>) Tuple1::get0)
        .thenComparing(Tuple1::get0);

Map<Tuple1<String>, LongSummaryStatistics> grouped = join.stream()
        .collect(groupingBy(t -> Tuples.of(t.get4().getNName()),
                () -> new TreeMap<>(comparator),
                summarizingLong(t->t.get2().getLDiscount()*(1-t.get2().getLDiscount()))
        ));

How can I resolve this?


Solution

  • So the problem is that +, -, *, /, ... are not working with BigDecimals. You have to use .add(), .subtract(), .multiply(), .divide(), ... methods for calculations.

    If it is possible, you can use BigDecimal.longValue() or BigDecimal.longValueExact() to convert the BigDecimals to long values to use them in your calculation:

    Map<Tuple1<String>, LongSummaryStatistics> grouped = join.stream()
            .collect(Collectors.groupingBy(Tuples::of,
                    () -> new TreeMap<>(comparator),
                    Collectors.summarizingLong(t -> t.get2().getLDiscount().longValue() *
                            (1 - t.get2().getLDiscount().longValue()))
            ));
    

    Alternatively you can du the whole calculation with BigDecimal and convert the value to long at the end:

    Map<Tuple1<String>, LongSummaryStatistics> grouped = join.stream()
            .collect(Collectors.groupingBy(Tuples::of,
                    () -> new TreeMap<>(comparator),
                    Collectors.summarizingLong(t -> t.get2().getLDiscount()
                            .multiply(BigDecimal.ONE
                            .subtract(t.get2().getLDiscount())).longValue())
            ));
    

    If both solutions do not work for you you have to write an own collection for BigDecimalSummaryStatistics or just calculate the values you need directly. You can read this question for summarizing BigDecimal values using Java Stream.