假设我有一个Collection,和一个Predicate匹配我想从中移除的元素Collection.但我不只是想丢弃它们,我想将匹配的元素移动到一个新的集合中.我会做一些像这样在Java 7中:
List<E> removed = new LinkedList<>();
for (Iterator<E> i = data.iterator(); i.hasNext();) {
E e = i.next();
if (predicate.test(e)) {
removed.add(e);
i.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
我很好奇是否有流/ Java 8方法可以做到这一点. Collections.removeIf()不幸的是简单地返回一个boolean(甚至没有删除元素的数量?太糟糕了.)我设想这样的东西(虽然当然.removeAndYield(Predicate)不存在):
List<E> removed = data.removeAndYield(predicate).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
注意:这个问题的灵感来自类似的问题 ; 这个问题是关于从集合中删除项目获取流的更一般情况.正如在链接问题中指出的那样,必要的解决方案可能更具可读性,但我很好奇是否甚至可以使用流.
编辑:显然,我们可以将任务分成两个单独的步骤,并假设适当的数据结构,它将是有效的.问题是可以在任意集合(可能没有效率.contains()等)上完成.
说我有以下代码
data.stream()
.map(x -> {
Object a = maybeReturnsNull(x);
return a == null ? defaultValue : a;
})
Run Code Online (Sandbox Code Playgroud)
我有一些可能正在返回的函数,null我将它应用于流的一个元素.然后我想确保将任何null结果更改为某个默认值.与使用上一个定义辅助变量a并在lambda表达式中使用代码块的示例相比,使用两个映射(如下例)之间是否存在任何显着差异?
data.stream()
.map(x -> maybeReturnsNull(x))
.map(x -> x == null ? defaultValue : x)
Run Code Online (Sandbox Code Playgroud)
有没有标准在哪里或不避免使用lambda函数的块语句?
我试图改变主意思考功能方式,并且最近面临一种情况,我需要从列表中获取元素,直到满足条件,我找不到一种简单的自然方式来实现这一点.显然我还在学习.
说我有这个清单:
List<String> tokens = Arrays.asList("pick me", "Pick me", "pick Me",
"PICK ME", "pick me and STOP", "pick me", "pick me and Stop", "pick me");
// In a non lambdas was you would do it like below
List<String> myTokens = new ArrayList<>();
for (String token : tokens) {
myTokens.add(token);
if (token.toUpperCase().endsWith("STOP")) {
break;
}
}
Run Code Online (Sandbox Code Playgroud)
提前感谢您的意见
注意:在发布之前,我读了一个谓词限制流,但我看不出如何能够根据我的问题调整答案.任何帮助将不胜感激.
我有兴趣确定一种方法,该方法返回排除另一个列表中元素的元素列表.
例如
List<Integer> multiplesOfThree = ... // 3,6,9,12 etc
List<Integer> evens = ... // 2,4,6,8 etc
List<Integer> others = multiplesOfThree.except(evens) // should return a list of elements that are not in the other list
Run Code Online (Sandbox Code Playgroud)
你怎么做到这一点?我找到了一种有点笨拙且难以阅读的方法....
multiplesOfThree.stream()
.filter(intval -> evens.stream().noneMatch(even -> even.intValue() == intval.intValue()))
Run Code Online (Sandbox Code Playgroud) Function接口的许多lambda都采用了这种形式
t -> {
// do something to t
return t;
}
Run Code Online (Sandbox Code Playgroud)
我经常这样做,所以我已经为此编写了一个方法.
static <T> Function<T, T> consumeThenReturn(Consumer<T> consumer) {
return t -> {
consumer.accept(t);
return t;
};
}
Run Code Online (Sandbox Code Playgroud)
这使我能够做到这样的非常好的事情:
IntStream.rangeClosed('A', 'Z')
.mapToObj(a -> (char) a)
.collect(Collectors.collectingAndThen(Collectors.toList(), consumeThenReturn(Collections::shuffle)))
.forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)
还有另一种方法可以在不依赖我自己的方法的情况下进行这样的转换吗?我错过的新API中有什么东西会让我的方法变得多余吗?
我遇到了一个场景,我想要小写HashMap的所有键(不要问为什么,我只需要这样做).HashMap有数百万条目.
起初,我以为我只是创建一个新的Map,迭代要小写的地图条目,并添加相应的值.这个任务应该每天只运行一次或类似的东西,所以我想我可以裸露这个.
Map<String, Long> lowerCaseMap = new HashMap<>(myMap.size());
for (Map.Entry<String, Long> entry : myMap.entrySet()) {
lowerCaseMap.put(entry.getKey().toLowerCase(), entry.getValue());
}
Run Code Online (Sandbox Code Playgroud)
但是,当我的服务器在这一次过载时,我正要复制Map时,会导致一些OutOfMemory错误.
现在我的问题是,如何以最小的内存占用来完成这项任务?
在小写后删除每个键 - 添加到新Map帮助?
我可以利用java8流来加快速度吗?(例如这样的事情)
Map<String, Long> lowerCaseMap = myMap.entrySet().parallelStream().collect(Collectors.toMap(entry -> entry.getKey().toLowerCase(), Map.Entry::getValue));
Run Code Online (Sandbox Code Playgroud)
更新
似乎它是一个Collections.unmodifiableMap所以我没有选择
在小写之后移除每个键 - 添加到新地图
我有一个像这样的对象流:
"0", "1", "2", "3", "4", "5",
Run Code Online (Sandbox Code Playgroud)
如何将其转换为对的流:
{ new Pair("0", "1"), new Pair("2", "3"), new Pair("4", "5")}.
Run Code Online (Sandbox Code Playgroud)
流大小未知.我正在从一个可能很大的文件中读取数据.我只有收集器的迭代器,我使用spliterator将此迭代器转换为流.我知道这是使用StreamEx处理相邻对的答案: 从流中收集连续对 可以在java或StreamEx中完成吗?谢谢
规范是否保证顺序 Java Streams 上的所有操作都在当前线程中执行?("forEach"和"forEachOrdered"除外)
我明确要求规范,而不是当前的实现.我可以自己查看当前的实现,不需要打扰你.但实现可能会改变,还有其他实现.
我问因为ThreadLocals:我使用的是一个内部使用ThreadLocals的Framework.即使像company.getName()这样的简单调用最终也会使用ThreadLocal.我无法改变该框架的设计方式.至少不在理智的时间内.
这里的规范似乎令人困惑.包"java.util.stream"的文档说明:
如果行为参数确实有副作用,除非明确说明,否则不能保证这些副作用对其他线程的可见性,也不保证同一流管道中"相同"元素的不同操作在同一个线程中执行.
...
即使当管道被约束以产生结果,其与流源的遭遇顺序一致(例如,IntStream.range(0,5).parallel()地图(X - > X*2).toArray( )必须产生[0,2,4,6,8]),不能保证制成,以作为对于所述映射器函数被应用到各个元件,或为了在什么螺纹任何行为参数被执行对于给定的元件.
我将其解释为:流上的每个操作都可以在不同的线程中发生.但是"forEach"和"forEachOrdered"的文档明确指出:
对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.
如果每个流操作都可能发生在未指定的线程中,那么该语句将是多余的.因此恰恰相反:串行流上的所有操作都保证在当前线程中执行,除了"forEach"和"forEachOrdered"?
我搜索了关于"Java","Stream"和"ThreadLocal"组合的权威答案,但没有发现任何内容.该关闭的事情是由一个答案作者Brian Goetz在这里对堆栈溢出一个相关的问题,但它是有关订单,而不是线程,它只是对"的forEach",而不是其他流的方法:是否Stream.forEach尊重遇到顺序流的顺序?
我无法理解为什么并行流和流为完全相同的语句提供不同的结果.
List<String> list = Arrays.asList("1", "2", "3");
String resultParallel = list.parallelStream().collect(StringBuilder::new,
(response, element) -> response.append(" ").append(element),
(response1, response2) -> response1.append(",").append(response2.toString()))
.toString();
System.out.println("ResultParallel: " + resultParallel);
String result = list.stream().collect(StringBuilder::new,
(response, element) -> response.append(" ").append(element),
(response1, response2) -> response1.append(",").append(response2.toString()))
.toString();
System.out.println("Result: " + result);
Run Code Online (Sandbox Code Playgroud)
ResultParallel:1,2,3
结果:1 2 3
有人可以解释为什么会发生这种情况以及如何让非并行版本得到与并行版本相同的结果?
为什么会出错?我以为map可以回报任何价值.
var s = IntStream.rangeClosed(1, 5).map(String::valueOf).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
| 错误:| 不兼容的类型:方法引用中的错误返回类型| java.lang.String无法转换为int | var s = IntStream.rangeClosed(1,5).map(String :: valueOf).collect(Collectors.toList()); |
^ ^ -------------
java ×10
java-stream ×10
java-8 ×8
lambda ×2
hashmap ×1
map-function ×1
streamex ×1
thread-local ×1