在我的示例中,我尝试从一系列字符创建一个ASCII表。我设法用一个List
的字符串来做到这一点,但是失败了,并带有一个字符数组。
我收到一个错误,提示Character::hashCode
无法在Collectors.toMap()
中解决。
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);
}
}
答案 0 :(得分:5)
.chars()
给您一个IntStream
,它是原始int
的流,而不是字符流(more info)。这就是为什么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
,因为它对您要使用哪种方法含糊不清,因为有两种可能:
int hashCode(char value)
您可以从这段代码中看到,它们都满足toMap()
的第一个参数:
Function<Character, Integer> f1 = e -> Character.hashCode(e);
Function<Character, Integer> f2 = e -> e.hashCode();
要解决此问题,可以将Object::hashCode
用于非静态方法调用。
答案 1 :(得分:2)
首先,您需要将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()));
答案 2 :(得分:2)
由于在CharBuffer::chars
之后使用方法collect()
返回了IntStream
,所以唯一可以使用的收集方法是IntStream::collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner)
接受3个参数。
如果要使用单参数收集方法,请将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()));