我在寻找最佳解决方案时遇到问题(这不是多次使用 forEach
)。
我有对象 A
、B
和 C
。对象B
包含一组对象C(即
B->Set`)。
我收到了 Map, B>
,我需要将其转换为 Map>
。
流库中是否有任何函数可以提供这种特定的解决方案?
我现在想出的解决方案是通过forEach
来处理这个地图。
在每次迭代中,我都会合并地图 Map>
中每个 A
的 C
集。这是解决方案的概要(里面发生了很多事情,b->c是发生的事情的快捷方式)。
通过创建 Map>,在每次迭代中我为每个迭代提供先前集合的合并。这是解决方案的概要(里面发生了很多事情,b->c是正在发生的事情的快捷方式)。
Map<A, Set<C>> aSetCMap = new HashMap<>();
for (Map.Entry<Set<A>, B> entry : setABMap.EntrySet()) {
var setA = entry.getKey();
var setC = b.transformC();
setA.forEach(item -> aSetCMap.merge(item, setC,
(current, added) -> Streams.concat(current.stream(), added.stream())
.collect(Collectors.toSet())));
}
我想出的解决方案是一种在 O(n^3) 时间内完成的奇怪方法。我正在使用它的东西需要高性能,因此我的问题。
I'm having a problem with finding an optimal solution (which is not multiple usage of forEach
).
I have objects A
, B
and C
. Object B
contains set of objects C (i.e.
B->Set`).
I'm being provided with a Map<Set<A>, B>
which I need to turn into a Map<A,Met<C>>
.
Is there any function in streams library that provides this particular solution?
The solution I came up with for now is to process this map through forEach
.
With each iteration, I'm merging sets of C
for each A
in the map Map<A,Set<C>>
. Here is outline of solution (there is a lot of things happening inside, the b->c is shortcut of whats happening).
With creating Map<A,Set<C>>
where in each iteration I'm providing a merger of previous sets for each of them. Here is the outline of solution(there are a lot of things happening inside, the b->c is shortcut of what's happening).
Map<A, Set<C>> aSetCMap = new HashMap<>();
for (Map.Entry<Set<A>, B> entry : setABMap.EntrySet()) {
var setA = entry.getKey();
var setC = b.transformC();
setA.forEach(item -> aSetCMap.merge(item, setC,
(current, added) -> Streams.concat(current.stream(), added.stream())
.collect(Collectors.toSet())));
}
The solution I came up with is a wonky way to do it in O(n^3) time. The thing I'm using it needs high performance, thus my question.
发布评论
评论(1)
您需要展平每个条目
Map.Entry, B>
。并将每个对象A
与从对象B
提取的Set
相关联。之后,通过使用
Collectors.toMap()
风格来应用collect()
,它采用三个参数:一个 keyMapper、一个 valueMapper 和一个 mergeFunction (需要组合映射到同一对象A
的集合)上面显示的方法适用于以下情况这
Set
可以在恒定时间内从对象B
获得。在这里我依赖你的话:如果此操作需要额外的处理(我在代码中看到一个方法
transformC()
)并创建一个新的每次调用transformC()
后设置,然后对于源映射中的每个条目,必须仅执行一次(即使用多行 lambda )。对于基于流的解决方案的时间复杂度,您对性能改进的期望将不会实现(假设迭代解决方案中没有逻辑错误)。
注意,使用可变对象 (
Set
) 作为键的情况本身就是恶性的,可能会导致不正确的行为。You need to flatten each entry
Map.Entry<Set<A>, B>
. And associate each objectA
with aSet<C>
extracted from the objectB
.After that, apply
collect()
by using a flavor ofCollectors.toMap()
which takes three arguments: a keyMapper, a valueMapper and a mergeFunction (which is needed to combine sets mapped to the same objectA
)The approach shown above is applicable if the
Set<C>
could be obtained from an objectB
in a constant time. Here I rely on your words:If this action entails an additional processing (I see a method
transformC()
in your code) and creates a new set after each invocation oftransformC()
, then for each entry in the source map it must be done only once (i.e. use multiline lambda).In regard to time complexity of stream-based solution, your expectation of performance improvement will not come true (assuming that there's no logical fault in the iterative solution).
Note, the situation when a mutable object (
Set<A>
) is used as a key is vicious by itself and could cause incorrect behavior.