标签: java-8

使用流将列表的收集与单个值组合

我有以下数据:

 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)

我知道有一个收集方法的流,但我不明白如何使用它来收集同一个类的一个值和值列表.

java list java-8

17
推荐指数
1
解决办法
1195
查看次数

以某种方式使用错误的JDK(?)构建Android应用程序

我最近更新了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与Jav​​a 8并不完全相同.特别是Android的实现ConcurrentHashMap.keySet()返回一个Set,而Java 8的实现则ConcurrentHashMap.keySet()返回一个KeySetView.

不知何故,Android Studio已经设法使用标准的Java 8 JDK编译我的应用程序,因此在运行时期望找到带有签名的方法KeySetView<K,V> keySet().但是,Android ConcurrentHashMap没有这个签名的方法,所以我得到了一个NoSuchMethodError …

java android concurrenthashmap java-8 android-studio-3.0

17
推荐指数
1
解决办法
1487
查看次数

如何只筛选出与Java顺序流中的谓词不匹配的第一个元素?

我在Java流操作中遇到了边缘情况......

我想编码以下行为:"从任意一篮子水果中收集20个最小的,除了最小的梨,因为我们不希望这样."

额外的奖励:来的篮子可能根本没有任何梨.

例子 :

  • 从[Pear 5,Apple 1,Apple 2,Apple 10,Pear 3,Pear 7]开始,我们需要[Apple 1,Apple 2,Pear 5,Pear 7,Apple 10].
  • 从[Apple 4,Apple 7,Pear 8,Pear 2,Pear 3]开始,我们想要[Pear 3,Apple 4,Apple 7,Pear 8].

到目前为止,我正迈出这一步:

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 …

java filtering java-8 java-stream

17
推荐指数
4
解决办法
915
查看次数

将CompletableFuture <Stream <T >>转换为Publisher <T>是否正确?

允许对结果流进行多次迭代,CompletableFuture<Stream<String>>我正在考虑以下方法之一:

  1. 将生成的未来转换为CompletableFuture<List<String>>:teams.thenApply(st -> st.collect(toList()))

  2. 将生成的未来转换为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).使用AsyncHttpClientGson我们有:

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>>:

  • [PROS] List<String>将继续收集,当我们需要继续处理未来的结果时,可能已经完成了.
  • [CONS]宣言冗长.
  • [CONS]如果我们只想使用它一次,那么我们就不需要收集那些物品了List<T>.

Flux<String> …

java java-8 rx-java project-reactor completable-future

17
推荐指数
1
解决办法
2030
查看次数

使用Collections.sort后在List中添加了新的排序方法

java.util.List当我们有一个使用排序列表的规定时,为什么在java 8中添加了一个新的排序方法Collections.sort

java collections list java-8

17
推荐指数
2
解决办法
1309
查看次数

什么更有效:排序流或排序列表?

假设我们在集合中有一些项目,我们想要使用某个比较器对它们进行排序,期望列表中的结果:

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并没有真正启发我.

java arraylist java-8 java-stream

17
推荐指数
2
解决办法
3503
查看次数

指定before/after :: operator的通用方法引用类型

以下方法引用之间有什么区别,

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)

案件有特殊名称吗?有没有类似用法的例子?

java generics java-8 method-reference

17
推荐指数
2
解决办法
656
查看次数

Java 8+流:检查列表的对象实例的两个字段的顺序是否正确

标题可能有点模糊,但这是我所拥有的(在私有化代码中):

包含一些字段的类,包括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)

java sorting boolean-expression java-8 java-stream

17
推荐指数
2
解决办法
2266
查看次数

可选isPresent vs orElse(null)

我在我的项目中更新了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)

或者,我错过了第三种更好的方法吗?我经历了几个问题和一些文章,但我没有找到明确的答案.

java java-8 spring-data-jpa

17
推荐指数
3
解决办法
6633
查看次数

如何转换Instant到LocalDate

我有一个来自一个源的Instant,根据规范,它应该是一个LocalDate,但是在LocalDate中没有看到任何转换方法.做这个的最好方式是什么?

java-8 localdate java.time.instant java.time

17
推荐指数
4
解决办法
2万
查看次数