Gho*_*ica 29 java lambda java-stream
我有一种方法必须Set<K> keysToRemove
从一些(可能大)中删除(小)中列出的任何元素Map<K,V> from
。但是removeAll()
不这样做,因为我需要返回实际上已删除的所有键,因为映射可能包含或可能不包含需要删除的键。
老式的代码很简单:
public Set<K> removeEntries(Map<K, V> from) {
Set<K> fromKeys = from.keySet();
Set<K> removedKeys = new HashSet<>();
for (K keyToRemove : keysToRemove) {
if (fromKeys.contains(keyToRemove)) {
fromKeys.remove(keyToRemove);
removedKeys.add(keyToRemove);
}
}
return removedKeys;
}
Run Code Online (Sandbox Code Playgroud)
使用流写的相同:
Set<K> fromKeys = from.keySet();
return keysToRemove.stream()
.filter(fromKeys::contains)
.map(k -> {
fromKeys.remove(k);
return k;
})
.collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)
我发现这更加简洁,但是我也发现lambda太笨拙了。
任何建议如何以较少笨拙的方式实现相同结果?
Hol*_*ger 24
“老式代码”应该是
public Set<K> removeEntries(Map<K, ?> from) {
Set<K> fromKeys = from.keySet(), removedKeys = new HashSet<>(keysToRemove);
removedKeys.retainAll(fromKeys);
fromKeys.removeAll(removedKeys);
return removedKeys;
}
Run Code Online (Sandbox Code Playgroud)
由于您说的keysToRemove
很小,因此复制开销可能无关紧要。否则,请使用循环,但不要进行两次哈希查找:
public Set<K> removeEntries(Map<K, ?> from) {
Set<K> fromKeys = from.keySet();
Set<K> removedKeys = new HashSet<>();
for(K keyToRemove : keysToRemove)
if(fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
return removedKeys;
}
Run Code Online (Sandbox Code Playgroud)
您可以将与流一样的逻辑表示为
public Set<K> removeEntries(Map<K, ?> from) {
return keysToRemove.stream()
.filter(from.keySet()::remove)
.collect(Collectors.toSet());
}
Run Code Online (Sandbox Code Playgroud)
但是,由于这是一个有状态的过滤器,因此不建议使用。更干净的变体是
public Set<K> removeEntries(Map<K, ?> from) {
Set<K> result = keysToRemove.stream()
.filter(from.keySet()::contains)
.collect(Collectors.toSet());
from.keySet().removeAll(result);
return result;
}
Run Code Online (Sandbox Code Playgroud)
而且,如果您想最大限度地利用“流式”用法,则可以替换from.keySet().removeAll(result);
为from.keySet().removeIf(result::contains)
,价格昂贵,因为它在较大的地图上进行迭代;或者替换为result.forEach(from.keySet()::remove)
,它虽然没有缺点,但可读性却不高比removeAll
。
总而言之,“老式代码”比这要好得多。
Ole*_*hov 13
更简洁的解决方案,但在通话中仍会产生有害的副作用filter
:
Set<K> removedKeys =
keysToRemove.stream()
.filter(fromKeys::remove)
.collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)
Set.remove
true
如果set
包含指定的元素,则已经返回。
PS最后,我可能会坚持使用“老式代码”。
我不会为此使用Streams。我会利用keepAll:
public Set<K> removeEntries(Map<K, V> from) {
Set<K> matchingKeys = new HashSet<>(from.keySet());
matchingKeys.retainAll(keysToRemove);
from.keySet().removeAll(matchingKeys);
return matchingKeys;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1458 次 |
最近记录: |