ytt*_*rrr 10 java java-8 java-stream
我正在尝试收集丢弃很少使用的项目的流,如下例所示:
import java.util.*;
import java.util.function.Function;
import static java.util.stream.Collectors.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import org.junit.Test;
@Test
public void shouldFilterCommonlyUsedWords() {
// given
List<String> allWords = Arrays.asList(
"call", "feel", "call", "very", "call", "very", "feel", "very", "any");
// when
Set<String> commonlyUsed = allWords.stream()
.collect(groupingBy(Function.identity(), counting()))
.entrySet().stream().filter(e -> e.getValue() > 2)
.map(Map.Entry::getKey).collect(toSet());
// then
assertThat(commonlyUsed, containsInAnyOrder("call", "very"));
}
Run Code Online (Sandbox Code Playgroud)
我觉得有可能做得更简单 - 我是对的吗?
Map除非您希望接受非常高的CPU复杂性,否则无法创建.
但是,您可以删除第二个 collect操作:
Map<String,Long> map = allWords.stream()
.collect(groupingBy(Function.identity(), HashMap::new, counting()));
map.values().removeIf(l -> l<=2);
Set<String> commonlyUsed=map.keySet();
Run Code Online (Sandbox Code Playgroud)
请注意,在Java 8中,HashSet仍然包装a HashMap,所以当你想要a时,使用keySet()a HashMap,在Set当前实现的情况下不会浪费空间.
当然,Collector如果感觉更"流" ,你可以隐藏后处理:
Set<String> commonlyUsed = allWords.stream()
.collect(collectingAndThen(
groupingBy(Function.identity(), HashMap::new, counting()),
map-> { map.values().removeIf(l -> l<=2); return map.keySet(); }));
Run Code Online (Sandbox Code Playgroud)
不久前我为我的图书馆写了一个实验方法:distinct(atLeast)
public StreamEx<T> distinct(long atLeast) {
if (atLeast <= 1)
return distinct();
AtomicLong nullCount = new AtomicLong();
ConcurrentHashMap<T, Long> map = new ConcurrentHashMap<>();
return filter(t -> {
if (t == null) {
return nullCount.incrementAndGet() == atLeast;
}
return map.merge(t, 1L, (u, v) -> (u + v)) == atLeast;
});
}
Run Code Online (Sandbox Code Playgroud)
所以我们的想法是像这样使用它:
Set<String> commonlyUsed = StreamEx.of(allWords).distinct(3).toSet();
Run Code Online (Sandbox Code Playgroud)
这执行了状态过滤,看起来有点难看。我怀疑这个功能是否有用,因此我没有将其合并到 master 分支中。尽管如此,它还是在单流传递中完成了工作。也许我应该恢复它。同时,您可以将此代码复制到静态方法中并像这样使用它:
Set<String> commonlyUsed = distinct(allWords.stream(), 3).collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)
更新(2015/05/31):我将该distinct(atLeast)方法添加到了 StreamEx 0.3.1 中。它是使用自定义 spliterator实现的。基准测试表明,对于顺序流,此实现比上述状态过滤要快得多,并且在许多情况下,它也比本主题中提出的其他解决方案更快。null如果在流中遇到它,它也能很好地工作(groupingBy收集器不支持null作为类,因此如果遇到groupingBy基于 - 的解决方案将失败)。null
| 归档时间: |
|
| 查看次数: |
5397 次 |
| 最近记录: |