Java流中无法解析Character::hashCode方法

3
在我的示例中,我尝试从字符序列创建 ASCII 表格。我使用字符串的列表List成功实现了它,但是使用字符的数组失败了。
我收到一个错误,指出在Collectors.toMap()中无法解析Character :: hashCode
Error:(26, 17) java: method collect in interface java.util.stream.IntStream cannot be applied to given types;
  required: java.util.function.Supplier<R>,java.util.function.ObjIntConsumer<R>,java.util.function.BiConsumer<R,R>
  found: java.util.stream.Collector<java.lang.Object,capture#1 of ?,java.util.Map<java.lang.Object,java.lang.Object>>
  reason: cannot infer type-variable(s) R
    (actual and formal argument lists differ in length)
Error:(26, 42) java: incompatible types: cannot infer type-variable(s) T,K,U,T
    (argument mismatch; invalid method reference
      incompatible types: java.lang.Object cannot be converted to char)

有没有一种方法可以实现这个?
public class JavaCollectToMapEx2 {

    public static void main(String[] args) {
        // list of ASCII characters
        var chars = List.of("a", "b", "c", "d", "e", "f",
                "g", "h", "i", "j", "k", "l", "m", "n",
                "o", "p", "q", "r", "s", "t", "u", "v",
                "w", "x", "y", "z");

//      CharSequence chars2 = "abcdefghijklmnopqrstuvwxyz";
        char[] letters = "abcdefghijklmnopqrstuvwxyz".toCharArray();

        // Map to represent ASCII character table
        Map<Integer, String> asciiMap = chars.stream()
           .collect(Collectors.toMap(String::hashCode, Function.identity()));

        Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars() 
            .collect(Collectors.toMap(Character::hashCode, Function.identity()));

        System.out.println(asciiMap);
        System.out.println(asciiMap2);
    }
}

没有错误信息吗? - user85421
我已经添加了完整的错误信息。 - Jan Bodnar
3个回答

6

.chars() 返回的是一个原始类型为int的流,而不是字符流(更多信息)。这就是为什么在Character上没有方法引用可用的原因。

要得到您要查找的内容,首先需要一个Stream<Character>

Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters)
        .chars()
        .mapToObj(e -> (char) e)
        .collect(Collectors.toMap(e -> e.hashCode(), Function.identity()));

现在,你仍然需要解决使用方法引用获取哈希码的问题。由于有两个可能的方法,Character::hashCode无法确定您想使用哪个方法:

  1. Object#hashCode的重写版本,
  2. 静态方法int hashCode(char value)

从这段代码中可以看出,这两种方法都满足toMap()的第一个参数:

Function<Character, Integer> f1 = e -> Character.hashCode(e);
Function<Character, Integer> f2 = e -> e.hashCode();

为了解决这个问题,您可以使用Object::hashCode来进行非静态方法调用。

1
关于发布的编译器错误,实际问题是 IntStream 没有 collect(Collector) 方法。另一种替代方法是 CharBuffer.wrap(letters) .chars() .boxed() .collect(Collectors.toMap(Function.identity(), e -> (char)e)); - Holger

3

由于您在CharBuffer::chars之后使用了collect()方法,该方法返回IntStream,因此您只能使用带有3个参数的IntStream::collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner)收集方法。

如果您想要使用一个参数的收集方法,请在其前面加上IntStream::boxed以返回Stream<Integer>。然后,Character::hashCode方法就会变得模糊不清,无法使用lambda表达式:

为避免这种情况,可以使用更好的方法mapToObj直接将其转换为char,而不需要装箱,然后使用继承自`Object`的Object::hashCode方法。

Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars()
    .mapToObj(ch -> (char) ch)
    .collect(Collectors.toMap(Object::hashCode, Function.identity()));

2

首先,您需要将IntStream映射到Stream<Character>。但是之后,您不能使用方法引用Character::hashCode,因为它是模糊的(对象级别和类级别):

最初的回答:

首先,您需要将IntStream映射到Stream<Character>。但是之后,您不能使用方法引用Character::hashCode,因为它是模糊的(对象级别和类级别):

Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars()
        .mapToObj(i -> (char) i)
        .collect(Collectors.toMap(i -> Character.hashCode(i), Function.identity()));

或者你可以直接使用 Object::hashCode 而不是 i -> Character.hashCode(i),因为 Character 类重写了它的 hashCode() 方法,使用的是 Character.hashCode()


public final class Character ... {
    @Override
    public int hashCode() {
        return Character.hashCode(value);
    }
}

最终你可以直接使用这个:

所以最后你可以只使用这个:

Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars()
        .mapToObj(i -> (char) i)
        .collect(Collectors.toMap(Object::hashCode, Function.identity()));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接