我有以下数据:
CustomClass first = new CustomClass(1, Arrays.asList(1, 2, 3));
CustomClass second = new CustomClass(5, Arrays.asList(6,7,8));
List<CustomClass> list = Arrays.asList(first, second);
Run Code Online (Sandbox Code Playgroud)
现在我想将这些数据收集到一个列表中,该列表包含CustomClass其列表中的值和值.
我想得到这个: 1, 1, 2, 3, 5, 6, 7, 8
这是我实施的:
list.stream().forEach(item -> {
result.add(item.value);
item.values.stream().forEach(seconditem -> result.add(seconditem));
});
Run Code Online (Sandbox Code Playgroud)
我知道有一个收集方法的流,但我不明白如何使用它来收集同一个类的一个值和值列表.
我最近更新了Android Studio 3的Android项目.我想支持Java 8语言功能,因此在build.gradle中添加了以下内容:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
Run Code Online (Sandbox Code Playgroud)
然后我在Android 8.0.0设备上运行我的应用程序.在运行时我看到了
java.lang.NoSuchMethodError: No virtual method keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; in class Ljava/util/concurrent/ConcurrentHashMap; or its super classes (declaration of 'java.util.concurrent.ConcurrentHashMap' appears in /system/framework/core-oj.jar)
Run Code Online (Sandbox Code Playgroud)
我认为这与keySet()Java 8 中的签名从返回Set<K>到返回的事实有关KeySetView<K,V>.
导致异常的行如下所示:
for (Long id : mSomeMap.keySet())
Run Code Online (Sandbox Code Playgroud)
KeySetView实现Set,当然Iterable,所以无论这条线被解释为Java 7还是Java 8,我都认为它可以工作.我对Java基础知识的理解是粗略的 - 这里发生了什么?
更新
到目前为止,我的愚蠢理解是:
虽然Android现在支持一些Java 8语言功能,但它的API与Java 8并不完全相同.特别是Android的实现ConcurrentHashMap.keySet()返回一个Set,而Java 8的实现则ConcurrentHashMap.keySet()返回一个KeySetView.
不知何故,Android Studio已经设法使用标准的Java 8 JDK编译我的应用程序,因此在运行时期望找到带有签名的方法KeySetView<K,V> keySet().但是,Android ConcurrentHashMap没有这个签名的方法,所以我得到了一个NoSuchMethodError …
我在Java流操作中遇到了边缘情况......
我想编码以下行为:"从任意一篮子水果中收集20个最小的,除了最小的梨,因为我们不希望这样."
额外的奖励:来的篮子可能根本没有任何梨.
例子 :
到目前为止,我正迈出这一步:
output = basket.stream()
.sorted(Comparator.comparing(Fruit::getSize))
//.filter(???)
.limit(20)
.collect(fruitCollector);
Run Code Online (Sandbox Code Playgroud)
这似乎是状态 lambda过滤器的情况,我不知道该怎么做.
我不能使用局部firstPear布尔值并true在过滤第一个梨之后将其设置为,因为lambda中的所有局部变量必须是final.
最糟糕的情况我可以将篮子分成两个,梨和非梨,对梨进行分类,如果有的话,适当地对它们进行子目录.这似乎非常低效和丑陋.有没有更好的办法?
这里发布的答案有很多种,而且大多数都是有效的.为了回馈社区,我整理了一个小测试工具来比较这些算法的性能.
这种比较并没有我想要的那么广泛 - 已经有3周了.它仅涵盖简单项目的顺序处理的用法.随意提供测试工具,并添加更多测试,更多基准或您自己的实现.
我的分析:
Algorithm | Author | Perf | Comments -------------------------------------------------------------------------------- Indexed removal | Holger | Best | Best overall, somewhat obscure Stateful predicate | pedromss | Best …
允许对结果流进行多次迭代,CompletableFuture<Stream<String>>我正在考虑以下方法之一:
将生成的未来转换为CompletableFuture<List<String>>:teams.thenApply(st -> st.collect(toList()))
将生成的未来转换为Flux<String>缓存:Flux.fromStream(teams::join).cache();
Flux<T>是Publisher<T>项目反应堆的实施.
使用案例:
我想Stream<String>从一个数据源获得一个具有顶级联赛球队名称的序列(例如),该数据源提供一个League对象Standing[](基于足球数据RESTful API,例如http://api.football-data.org/v1/ soccerseasons/445/leagueTable).使用AsyncHttpClient和Gson我们有:
CompletableFuture<Stream<String>> teams = asyncHttpClient
.prepareGet("http://api.football-data.org/v1/soccerseasons/445/leagueTable")
.execute()
.toCompletableFuture()
.thenApply(Response::getResponseBody)
.thenApply(body -> gson.fromJson(body, League.class));
.thenApply(l -> stream(l.standings).map(s -> s.teamName));
Run Code Online (Sandbox Code Playgroud)
要重新使用生成的流,我有两个选择:
1. CompletableFuture<List<String>> res = teams.thenApply(st -> st.collect(toList()))
2. Flux<String> res = Flux.fromStream(teams::join).cache()
Run Code Online (Sandbox Code Playgroud)
Flux<T>不那么冗长,并提供我所需要的一切.然而,在这种情况下使用它是否正确?
或者我应该使用CompletableFuture<List<String>>?或者还有其他更好的选择吗?
更新了一些想法(2018-03-16):
CompletableFuture<List<String>>:
List<String>将继续收集,当我们需要继续处理未来的结果时,可能已经完成了.List<T>.Flux<String> …
java.util.List当我们有一个使用排序列表的规定时,为什么在java 8中添加了一个新的排序方法Collections.sort
假设我们在集合中有一些项目,我们想要使用某个比较器对它们进行排序,期望列表中的结果:
Collection<Item> items = ...;
Comparator<Item> itemComparator = ...;
Run Code Online (Sandbox Code Playgroud)
其中一种方法是对列表中的项进行排序,例如:
List<Item> sortedItems = new ArrayList<>(items);
Collections.sort(sortedItems, itemComparator);
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用排序流:
List<Item> sortedItems = items
.stream()
.sorted(itemComparator)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
我想知道,哪种方法更有效率?排序流是否有任何优点(如多核上的紧固排序)?
从运行时复杂性/速度的角度来看,效率很高.
我不相信自己能够实现一个完美的基准,学习SortedOps并没有真正启发我.
以下方法引用之间有什么区别,
BiPredicate<List<String>,String> contains1 = List<String>::contains;
BiPredicate<List<String>,String> contains2 = List::<String>contains;
BiPredicate<List<String>,String> contains3 = List<String>::<String>contains;
Run Code Online (Sandbox Code Playgroud)
案件有特殊名称吗?有没有类似用法的例子?
标题可能有点模糊,但这是我所拥有的(在私有化代码中):
包含一些字段的类,包括BigDecimal和Date:
class MyObj{
private java.math.BigDecimal percentage;
private java.util.Date date;
// Some more irrelevant fields
// Getters and Setters
}
Run Code Online (Sandbox Code Playgroud)
在另一个类中,我有一个这些对象的列表(即java.util.List<MyObj> myList).我现在想要的是一个Java 8流来检查列表是否符合我的验证器的日期和百分比的正确顺序.
例如,以下列表将是真实的:
[ MyObj { percentage = 25, date = 01-01-2018 },
MyObj { percentage = 50, date = 01-02-2018 },
MyObj { percentage = 100, date = 15-04-2019 } ]
Run Code Online (Sandbox Code Playgroud)
但是这个列表是假的,因为百分比的顺序不正确:
[ MyObj { percentage = 25, date = 01-01-2018 },
MyObj { percentage = 20, date = 01-02-2018 },
MyObj { percentage = 100, …Run Code Online (Sandbox Code Playgroud) 我在我的项目中更新了Spring 8的依赖项,并被编译错误轰炸,其中方法定义findOne()已被替换findById(),现在返回一个Optional(如果我错了,请纠正我).
在重构时,我遇到了多种我可以选择采用的方法,因此我想要一些关于哪一种是首选的输入.
第一种方法:
ExpectedPackage ep = expectedPackageRepository.findById(1).orElse(null);
if(ep != null){
ep.setDateModified(new Date());
expectedPackageRepository.saveAndFlush(ep);
}
Run Code Online (Sandbox Code Playgroud)
第二种方法:
Optional<ExpectedPackage> ep = expectedPackageRepository.findById(1);
if(ep.isPresent()){
ep.get().setDateModified(new Date());
expectedPackageRepository.saveAndFlush(ep.get());
}
Run Code Online (Sandbox Code Playgroud)
或者,我错过了第三种更好的方法吗?我经历了几个问题和一些文章,但我没有找到明确的答案.
我有一个来自一个源的Instant,根据规范,它应该是一个LocalDate,但是在LocalDate中没有看到任何转换方法.做这个的最好方式是什么?