意外绑定 - 为什么我可以使用此收集器中的t扩展收藏品之类的东西?
嗨,我已经编写了此自定义收集器,用于将列表
elements转换为Multimap
:
public class MultiMapCollector implements Collector<Entity,
Map<String, Collection<String>>, Map<String, Collection<String>>> {
@Override
public Supplier<Map<String, Collection<String>>> supplier() {
return HashMap::new;
}
@Override
public BiConsumer<Map<String, Collection<String>>, Entity> accumulator() {
return (map, e) -> map.computeIfAbsent(e.getName(),
k -> new HashSet<>()).add(e.getValue());
}
@Override
public BinaryOperator<Map<String, Collection<String>>> combiner() {
return (map1, map2) -> {
map2.keySet().forEach(key -> map1.computeIfAbsent(key, k -> new HashSet<>()).addAll(map2.get(key)));
return map1;
};
}
@Override
public Function<Map<String, Collection<String>>, Map<String, Collection<String>>> finisher() {
return Collections::unmodifiableMap;
}
@Override
public Set<Characteristics> characteristics() {
return Set.of(Characteristics.UNORDERED);
}
}
现在我希望能够传递list> list
或SET
。
因此,代替map&lt; string,collection&lt; string&gt;&gt;
我想要类似map&lt&lt; string,v Extends collection&lt extents collection&gt;&gt;&gt;
的东西,
但是当我这样做时,我得到了一个模糊的错误说:
Unexpected Bounds
我做错了什么?
我似乎无法将其缠住。
Hi I have written this custom collector for converting a List
of elements into a Multimap
:
public class MultiMapCollector implements Collector<Entity,
Map<String, Collection<String>>, Map<String, Collection<String>>> {
@Override
public Supplier<Map<String, Collection<String>>> supplier() {
return HashMap::new;
}
@Override
public BiConsumer<Map<String, Collection<String>>, Entity> accumulator() {
return (map, e) -> map.computeIfAbsent(e.getName(),
k -> new HashSet<>()).add(e.getValue());
}
@Override
public BinaryOperator<Map<String, Collection<String>>> combiner() {
return (map1, map2) -> {
map2.keySet().forEach(key -> map1.computeIfAbsent(key, k -> new HashSet<>()).addAll(map2.get(key)));
return map1;
};
}
@Override
public Function<Map<String, Collection<String>>, Map<String, Collection<String>>> finisher() {
return Collections::unmodifiableMap;
}
@Override
public Set<Characteristics> characteristics() {
return Set.of(Characteristics.UNORDERED);
}
}
Now I want to be able to pass a List
or a Set
.
So instead of Map<String, Collection<String>>
I want something like Map<String, V extends Collection<String>>
But when I do that I get a vague error saying :
Unexpected Bounds
What am I doing wrong ?
I can't seem to wrap my head around this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要在类名称之后添加一个通用类型参数(让我们称其为
c
),而不是instentements
子句。然后,添加一个构造函数,该构造函数可吸引
供应商&lt; c&gt;
告诉您如何创建c
,并将供应商存储在某个地方。用新的HashSet&lt;()
用get
调用的所有出现。现在,每次创建
MultiMapCollector
时,您都需要传递供应商:如果您希望它使用
HashSet
当您不提供任何内容时使用默认值,请添加静态出厂方法并将构造函数私有化:就像
collector.groupingby
是一种工厂方法一样。更一般而言,您可以使用完整的下游收集器,而不仅仅是
供应商&lt; c&gt;
,这就是collectors.groupingby 的2-参数过载。
groupingby
只能处理分组,而下游收集器(第二参数)处理组。这是您将如何做到这一点的草图:
You need to add a generic type parameter (let's call it
C
) after the class name, not in theimplements
clause.Then, add a constructor that takes in a
Supplier<C>
telling you how to create aC
, and store the supplier somewhere. Replace all the occurrences ofnew HashSet<>()
withget
calls to the supplier instead.Now every time you create a
MultiMapCollector
, you need to pass in a supplier:If you want it to use a default of
HashSet
when you don't provide anything, add static factory methods and make the constructor private:Just like how
Collectors.groupingBy
is a factory method.More generally, you can take a full downstream collector instead of just a
Supplier<C>
, and that is what the 2-parameter overload ofCollectors.groupingBy
does.groupingBy
just handles the grouping, and the downstream collector (the 2nd argument) handles the groups.Here is a sketch of how you would do this:
如果要允许使用
集合的不同实现&lt; string&gt;
用作地图的值,则需要为MultiMapCollector
定义类型参数。您还需要修改代码以接受某种对象,例如供应商
,知道如何创建特定集合类型的实例。例如:
Note
MultiMapCollector
现在具有类型参数&lt; v扩展了Collection&lt; string&gt;&gt;
,并且在代码中其他任何地方collection&collection&lt lt; string&gt;
已用v
替换。然后,构造函数接受供应商?扩展v&gt;
,用于在comgualator()
消费者中创建v
的实例。另外,请注意,我更新了您的
combiner()
功能以使用MAP#MERGE(...)
,尽管这不是严格必要的。顺便说一句,如果您要实际查看
collectors.groupingby(...)
的实现方式,那么您始终可以查看源代码。If you want to allow different implementations of
Collection<String>
to be used as the values of your maps, then you need to define a type parameter for yourMultiMapCollector
. You'll also need to modify the code to accept some sort of object, such as aSupplier
, that knows how to create instances of the specific collection type.For example:
Note
MultiMapCollector
now has the type parameter<V extends Collection<String>>
, and that everywhere else in the code whereCollection<String>
was used has been replaced withV
. And then the constructor accepts aSupplier<? extends V>
which is used to create instances ofV
in theaccumulator()
consumer.Also, note I updated your
combiner()
function to make use ofMap#merge(...)
, though that's not strictly necessary.By the way, if you want to actually see how
Collectors.groupingBy(...)
is implemented, then you can always look at the source code.