编辑::我改写这个问题,以便它更清楚
我已经写了这段代码
List<ImmutablePair<Integer, Integer>> list = new ArrayList<ImmutablePair<Integer, Integer>>();
list.add(new ImmutablePair(1, 1));
list.add(new ImmutablePair(1, 1));
list.add(new ImmutablePair(1, 1));
list.add(new ImmutablePair(2, 2));
list.add(new ImmutablePair(2, 2));
list.add(new ImmutablePair(2, 2));
list.add(new ImmutablePair(3, 3));
list.add(new ImmutablePair(3, 3));
list.add(new ImmutablePair(3, 3));
Stream<ImmutablePair<Integer, Integer>> stream = list.stream();
Map<Integer, Integer> result = stream.collect(Collectors.groupingBy(
ImmutablePair::getLeft,
Collectors.mapping(
ImmutablePair::getRight,
Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight))
)
));
我想使用蒸汽处理此列表,以便输出是包含键(1、3),(2、6),(3、9)的映射
因此,基本上,我们将元组的左侧项目分组,然后对右侧项目求和。
此代码无法编译,编译器表示无法解析getLeft,getRight方法。
这是来自编译器的错误消息
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:229: error: method summingInt in class Collectors cannot be applied to given types;
Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight))
^
required: ToIntFunction<? super T#1>
found: Comparator<Object>
reason: no instance(s) of type variable(s) T#2,U exist so that Comparator<T#2> conforms to ToIntFunction<? super T#1>
where T#1,T#2,U are type-variables:
T#1 extends Object declared in method <T#1>summingInt(ToIntFunction<? super T#1>)
T#2 extends Object declared in method <T#2,U>comparing(Function<? super T#2,? extends U>)
U extends Comparable<? super U> declared in method <T#2,U>comparing(Function<? super T#2,? extends U>)
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:229: error: incompatible types: cannot infer type-variable(s) T,U
Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight))
^
(argument mismatch; invalid method reference
no suitable method found for getRight(Object)
method Pair.getRight() is not applicable
(actual and formal argument lists differ in length)
method ImmutablePair.getRight() is not applicable
(actual and formal argument lists differ in length))
where T,U are type-variables:
T extends Object declared in method <T,U>comparing(Function<? super T,? extends U>)
U extends Comparable<? super U> declared in method <T,U>comparing(Function<? super T,? extends U>)
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:229: error: invalid method reference
Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight))
^
non-static method getRight() cannot be referenced from a static context
where R is a type-variable:
R extends Object declared in class ImmutablePair
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:228: error: invalid method reference
ImmutablePair::getRight,
^
non-static method getRight() cannot be referenced from a static context
where R is a type-variable:
R extends Object declared in class ImmutablePair
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:226: error: invalid method reference
ImmutablePair::getLeft,
^
non-static method getLeft() cannot be referenced from a static context
where L is a type-variable:
L extends Object declared in class ImmutablePair
最佳答案
更新:会回答一个原始问题(revision 2)。 @ Shiraaz.M很好地回答了新问题。
您的Comparator
接受一对,因此您需要使用getRight
调用Collectors.mapping
:
Map<String, Optional<Movie>> map = ml.getDataAsStream()
.<ImmutablePair<String, Movie>>flatMap(x -> x.getGenre()
.map(g -> new ImmutablePair<String, Movie>(g, x)))
.collect(
Collectors.groupingBy(
ImmutablePair::getLeft,
Collectors.mapping(ImmutablePair::getRight,
Collectors.maxBy(Comparator.comparing(Movie::getVoteCount)))
));
请注意,根据使用的编译器,您可能需要显式指定一些类型,因为自动推断可能会失败。
实际上,我的StreamEx库很好地支持了这种情况,该库增强了标准Java流。通过编写以下代码可以实现相同的结果:
Map<String, Optional<Movie>> map = StreamEx.of(ml.getDataAsStream())
.cross(Movie::getGenre) // create (Movie, Genre) entries
.invert() // swap entries to get (Genre, Movie)
.grouping(Collectors.maxBy(Comparator.comparing(Movie::getVoteCount)));
最后请注意,使用
maxBy
收集器,您将获得Optional
值,该值无用,因为它们不能为空。对于maxBy/minBy
方案,最好使用具有自定义合并功能的toMap
收集器:Map<String, Movie> map = ml.getDataAsStream()
.<ImmutablePair<String, Movie>>flatMap(x -> x.getGenre()
.map(g -> new ImmutablePair<String, Movie>(g, x)))
.collect(Collectors.toMap(ImmutablePair::getLeft, ImmutablePair::getRight,
BinaryOperator.maxBy(Comparator.comparing(Movie::getVoteCount))));
或使用StreamEx:
Map<String, Movie> map = StreamEx.of(ml.getDataAsStream())
.cross(Movie::getGenre)
.invert()
.toMap(BinaryOperator.maxBy(Comparator.comparing(Movie::getVoteCount)));