假设我有一个在接口下面实现的对象列表:
public interface Summable<T> {
T add(T o1);
}
Run Code Online (Sandbox Code Playgroud)
假设我还有一些能够对这些对象求和的类:
public class Calculator<T extends Summable<T>> {
public T sum(final List<T> objects) {
if (null == objects) {
throw new IllegalArgumentException("Ups, list of objects cannot be null!");
}
T resultObject = null;
for (T object : objects) {
resultObject = object.add(resultObject);
}
return resultObject;
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用Java 8流实现相同的功能?
我正在玩一个定制的收藏家,但无法弄清楚一些简洁的解决方案.
我已经设法使用Java 8 Streams API编写解决方案,该解决方案首先按对象组合对象Route列表,然后计算每个组中对象的数量.它返回一个映射Route - > Long.这是代码:
Map<Route, Long> routesCounted = routes.stream()
.collect(Collectors.groupingBy(gr -> gr, Collectors.counting()));
Run Code Online (Sandbox Code Playgroud)
而Route类:
public class Route implements Comparable<Route> {
private long lastUpdated;
private Cell startCell;
private Cell endCell;
private int dropOffSize;
public Route(Cell startCell, Cell endCell, long lastUpdated) {
this.startCell = startCell;
this.endCell = endCell;
this.lastUpdated = lastUpdated;
}
public long getLastUpdated() {
return this.lastUpdated;
}
public void setLastUpdated(long lastUpdated) {
this.lastUpdated = lastUpdated;
}
public Cell getStartCell() {
return startCell;
}
public void setStartCell(Cell startCell) …Run Code Online (Sandbox Code Playgroud) 下面简单的java代码在操作数堆栈异常上发送 java.lang.VerifyError:Bad类型
public class TestJavaCodes {
int parentData = 0;
public void init() {
A ob = new B();
}
public static void main(String[] args) {
TestJavaCodes testJavaCodes = new TestJavaCodes();
testJavaCodes.init();
}
public static class A {
public A(MyLambdaFunc lambdaFunc) {
}
}
public class B extends A {
public B() {
super((data1, type) -> {
parentData = 1;
});
}
}
@FunctionalInterface
public static interface MyLambdaFunc {
public void onData(String data, int type);
} …Run Code Online (Sandbox Code Playgroud) 在Java 8上读了一下,我得到了这篇博文,解释了一些关于流和减少它们的内容,以及什么时候可以缩短缩减.在底部它表明:
注意在
findFirst或者findAny我们只需要与谓词匹配的第一个值(虽然findAny不能保证返回第一个).但是如果流没有排序,那么我们期望findFirst表现得像findAny.的操作allMatch,noneMatch并anyMatch可能不短路流,因为在所有可能需要评估所有的值,以确定操作者是否是true或false.因此,使用这些的无限流可能不会终止.
我得到了这个findFirst或者findAny可能会缩短减少量,因为一旦你找到了一个元素,你就不需要再进一步处理了.
但为什么这不可能allMatch,noneMatch并且anyMatch?因为allMatch,如果找到与谓词不匹配的一个,则可以停止处理.同样没有.而且anyMatch尤其是没有道理给我,因为它几乎等于findAny(除了返回什么)?
说这三个可能不会短路,因为它可能需要评估所有的值,也可以说findFirst/Any.
我缺少一些根本区别吗?我真的不明白发生了什么事吗?
我的项目已经开始使用java 7中的java 8.
切换到java 8后,我们发现消耗的内存随着时间的推移而越来越高.
以下是我们所做的调查:
现在剩下的唯一途径是分析内存如何在java 7和java 8中进行分发,特别是私有字节内存.任何想法或链接在这里将不胜感激.
注意:此javaw应用程序是基于swing的应用程序.
更新1:使用NMT工具分析本机内存并生成与基线相比占用的内存差异.我们发现堆保持相同但线程正在泄漏所有这些内存.因此Heap没有变化,我假设这个泄漏是由于本机代码.
所以挑战仍然存在.关于如何分析所有线程占用的内存的任何想法在这里都会有所帮助.以下是从本机内存跟踪中获取的快照.
在这张图片中,你可以看到88 MB的线程增加了.竞技场和资源处理数量增加了很多.
在这张图片中你可以看到这个Malloc中增加了73 MB.但是这里没有显示方法名称.

所以请在理解这两个截图时提供一些信息.
我有一个对象列表,其中有许多重复,有些字段需要合并.我想将它简化为仅使用Java 8 Streams的唯一对象列表(我知道如何通过old-skool方法执行此操作,但这是一个实验.)
这就是我现在所拥有的.我真的不喜欢这个,因为地图构建看起来无关紧要,而且values()集合是支持地图的视图,你需要将它包装成一个新的ArrayList<>(...)以获得更具体的集合.有没有更好的方法,也许使用更一般的减少操作?
@Test
public void reduce() {
Collection<Foo> foos = Stream.of("foo", "bar", "baz")
.flatMap(this::getfoos)
.collect(Collectors.toMap(f -> f.name, f -> f, (l, r) -> {
l.ids.addAll(r.ids);
return l;
})).values();
assertEquals(3, foos.size());
foos.forEach(f -> assertEquals(10, f.ids.size()));
}
private Stream<Foo> getfoos(String n) {
return IntStream.range(0,10).mapToObj(i -> new Foo(n, i));
}
public static class Foo {
private String name;
private List<Integer> ids = new ArrayList<>();
public Foo(String n, int i) {
name = n;
ids.add(i);
}
}
Run Code Online (Sandbox Code Playgroud) 假设我们有一个由唯一Strings 标识的对象集合,以及一个Tree定义它们层次结构的类.该类使用Mapfrom节点(由其ID表示)到Collection其各自子节点的s来实现.
class Tree {
private Map<String, Collection<String>> edges;
// ...
public Stream<String> descendants(String node) {
// To be defined.
}
}
Run Code Online (Sandbox Code Playgroud)
我想启用流式节点的后代.一个简单的解决方案是:
private Stream<String> children(String node) {
return edges.getOrDefault(node, Collections.emptyList()).stream();
}
public Stream<String> descendants(String node) {
return Stream.concat(
Stream.of(node),
children(node).flatMap(this::descendants)
);
}
Run Code Online (Sandbox Code Playgroud)
在继续之前,我想对此解决方案做出以下断言.(我对这些是正确的吗?)
从Stream返回的descendants消耗资源(时间和内存) - 相对于树的大小 - 以与手动编码递归相同的复杂度顺序行走.特别地,表示迭代状态(Streams,Spliterators,...)的中间对象形成堆栈,因此在任何给定时间的存储器要求与树的深度具有相同的复杂度.
据我所知此,只要我在执行终止操作Stream从返回descendants,根级别调用flatMap将导致所有包含Stream秒-一个用于每个(递归)呼叫descendants-被立即实现.因此,结果Stream …
import java.util.concurrent.Callable;
class Ideone
{
Callable<?> x = super::clone;
}
Run Code Online (Sandbox Code Playgroud)
使用Oracle JDK提供:
Main.java:6: error: incompatible types: invalid method reference
Callable<?> x = super::clone;
^
clone() has protected access in Object
Run Code Online (Sandbox Code Playgroud)
这没有意义,因为类应该能够访问其父级的受保护方法.这个表达式在Eclipse的编译器中运行良好.
还() -> super.clone()编译好......
这是一个错误吗?
我有一个从Google Places API中获取的Google PlaceSummary对象列表.我想通过他们的Google商家信息ID收集和分组,但也保留元素的顺序.我认为会起作用的是:
Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
places.stream()
.collect(Collectors.groupingBy(
PlaceSummary::getPlaceId,
LinkedHashMap::new,
Collectors.mapping(PlaceSummary::getPlaceId, toList())
));
Run Code Online (Sandbox Code Playgroud)
但它甚至不会编译.它看起来应该根据收集器上的Java API文档.
以前我有这个代码:
Map<String, List<PlaceSummary>> placesGroupedByPlaceId = places.stream()
.collect(Collectors.groupingBy(PlaceSummary::getPlaceId));
Run Code Online (Sandbox Code Playgroud)
但是.collect(),Streams API上的标准不保留后续元素的顺序HashMap(显然因为HashMaps是无序的).我希望输出为a,LinkedHashMap以便Map按每个桶的插入顺序排序.
但是,我建议的解决方案不能编译.首先,它不承认PlaceSummary::getPlaceId它,因为它说它不是一个功能 - 即使我知道它是.其次,它说我不能转换LinkedHashMap<Object, Object>成M. M应该是一个通用的集合,所以它应该被接受.
如何将List转换为LinkedHashMap使用Java Stream API?有简洁的方法吗?如果它太难理解我可能只是采用旧学前Java 8方法.
我注意到在将List转换为LinkedHashMap时还有另一个Stack Overflow答案,但是这没有我想要的解决方案,因为我需要收集'this'我正在迭代的对象.
在Java 8中,提供了各种方便的实用程序来从阵列构建高效的Spliterator.但是,没有提供工厂方法来构建带有比较器的Spliterator.显然,Spliterators可以附加比较器; 他们有getComparator()方法和SORTED财产.
图书馆作者如何构建SORTEDSpliterator?
java-8 ×10
java ×9
java-stream ×5
lambda ×2
algorithm ×1
collectors ×1
grouping ×1
java-7 ×1
native ×1
spliterator ×1