首页 > 解决方案 > “mapToInt(Integer::intValue)”和“mapToInt(Integer -> Integer.intValue())”有什么区别

问题描述

我知道它们具有相同的效果,但是为什么会Integer::intValue出错?

public class ResistorColorDuo {
    Map<String, Integer> colValueMap;

    public ResistorColorDuo(Map<String, Integer> colValueMap) {
        colValueMap.put("Black", 0);
        colValueMap.put("Brown", 1);
        colValueMap.put("Red", 2);
        colValueMap.put("Orange", 3);
        colValueMap.put("Yellow", 4);
        colValueMap.put("Green", 5);
        colValueMap.put("Blue", 6);
        colValueMap.put("Violet", 7);
        colValueMap.put("Grey", 8);
        colValueMap.put("White", 9);

        this.colValueMap = colValueMap;
    }

    public int getResistorValue(String... colors) {
        return Arrays.stream(colors).map(i -> colValueMap.get(i) *
                Math.pow(10, colors.length - (Arrays.asList(colors).indexOf(i) + 1)))
                .mapToInt(Integer::intValue) // Here occurs an exception
                .sum();
    }
}

上面的代码产生了一个错误:

不能从静态上下文中引用非静态方法

虽然它像这样工作得很好:

public int getResistorValue(String... colors) {
    return Arrays.stream(colors).map(i -> colValueMap.get(i) *
            Math.pow(10, colors.length - (Arrays.asList(colors).indexOf(i) + 1)))
            .mapToInt(Integer -> Integer.intValue())
            // Here is the difference
            .sum();
}

标签: javalambdajava-stream

解决方案


I'm not sure the error message you got is very informative (see the error message I got below). However, in your map step you are returning the result of Math.pow(), which is double. Hence your Stream becomes a Stream<Double>.

Trying to apply .mapToInt(Integer::intValue) fails, because Integer's intValue() requires an Integer instance.

When you use the lambda expression mapToInt(Integer -> Integer.intValue()), you should note that Integer is just the lambda parameter name, so it would have been less confusing to write mapToInt(n -> n.intValue()). Since n is a Double in this case, that lambda expression actually executes Double's intValue(), which works.

For a method reference to work, you need to use .mapToInt(Double::intValue).

EDIT: I tried similar code (I didn't feel like typing all the code from your image):

int sum = Stream.of ("1","2","3")
                .map (Integer::valueOf)
                .map(i -> Math.pow(i,2))
                .mapToInt(Integer::intValue)
                .sum();

and got a much better compilation error message:

The type Integer does not define intValue(Double) that is applicable here

This is fixed by changing the method reference as follows:

int sum = Stream.of ("1","2","3")
                .map (Integer::valueOf)
                .map(i -> Math.pow(i,2))
                .mapToInt(Double::intValue)
                .sum();

推荐阅读