我想知道,是否有一种首选方法可以从列表流中获取包含流中所有列表元素的集合.我可以想到两种方法:
final Stream<List<Integer>> stream = Stream.empty();
final List<Integer> one = stream.collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
final List<Integer> two = stream.flatMap(List::stream).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
第二个选项对我来说看起来更好,但我想第一个选项在并行流中效率更高.是否支持或反对这两种方法中的一种?
使用非并发数据结构源流的非干扰要求是否意味着在执行流管道期间我们无法更改数据结构元素的状态(除此之外我们无法更改源数据结构本身)?(问题1)
在关于非干扰的部分中,在流包描述中,它说:"对于大多数数据源,防止干扰意味着确保在流管道的执行期间根本不修改数据源."
这篇文章没有提到修改元素的状态?
例如,假设"形状"是非线程安全的集合(例如ArrayList),下面的代码是否被认为有干扰?(问题2)
shapes.stream()
.filter(s -> s.getColor() == BLUE)
.forEach(s -> s.setColor(RED));
Run Code Online (Sandbox Code Playgroud)
这个例子取自可靠的来源(至少可以说),所以它应该是正确的.但是,如果我改变stream()了parallelStream(),它仍然是安全和正确的吗?(问题3)
另一方面,另一个可靠来源Naftalin Maurice的"掌握Lambdas"清楚地表明,通过管道操作改变元素的状态(值)确实是干扰.从关于不干涉的部分(3.2.3):
"但是流的规则禁止对流源进行任何修改 - 包括,例如,通过任何线程更改元素的值,而不仅仅是管道操作."
如果书中所说的是正确的,是否意味着我们不能使用Stream API来修改元素的状态(使用forEach),并且必须使用常规迭代器(或for-each,或Iterable.forEach)来做到这一点?(问题4)
我一直试图理解和展示Java流如何在引擎盖下实现一种循环融合,以便将几个操作融合到一个通道中.
这是第一个例子:
Stream.of("The", "cat", "sat", "on", "the", "mat")
.filter(w -> {
System.out.println("Filtering: " + w);
return w.length() == 3;
})
.map(w -> {
System.out.println("Mapping: " + w);
return w.toUpperCase();
})
.forEach(w -> System.out.println("Printing: " + w));
Run Code Online (Sandbox Code Playgroud)
具有以下输出(每个元素的单个传递的融合非常清晰):
Filtering: The
Mapping: The
Printing: THE
Filtering: cat
Mapping: cat
Printing: CAT
Filtering: sat
Mapping: sat
Printing: SAT
Filtering: on
Filtering: the
Mapping: the
Printing: THE
Filtering: mat
Mapping: mat
Printing: MAT
Run Code Online (Sandbox Code Playgroud)
第二个例子是相同的,但我使用filter和map之间的sorted()操作:
Stream.of("The", "cat", "sat", "on", "the", "mat")
.filter(w -> {
System.out.println("Filtering: …Run Code Online (Sandbox Code Playgroud) 假设我们有一个标准的流操作方法链:
Arrays.asList("a", "bc", "def").stream()
.filter(e -> e.length() != 2)
.map(e -> e.length())
.forEach(e -> System.out.println(e));
Run Code Online (Sandbox Code Playgroud)
JLS中是否有关于流操作应用于列表元素的顺序的保证?
例如,是否保证:
"bc"之前,不会发生应用过滤谓词"a"?"def"之前,应用映射函数是不会发生的"a"?1将在之前打印3?注意:我在这里专门讨论stream(),而不是 parallelStream()预期映射和过滤等操作并行完成的地方.
让我们说我们有这样的事情:
LongStream.range(0, 10).parallel()
.filter(l -> {
System.out.format("filter: %s [%s]\n", l, Thread.currentThread().getName());
return l % 2 == 0;
})
.map(l -> {
System.out.format("map: %s [%s]\n", l, Thread.currentThread().getName());
return l;
});
Run Code Online (Sandbox Code Playgroud)
如果你运行这个程序输出将是这样的:
filter: 6 [main]
map: 6 [main]
filter: 5 [main]
filter: 4 [ForkJoinPool.commonPool-worker-2]
map: 4 [ForkJoinPool.commonPool-worker-2]
filter: 1 [ForkJoinPool.commonPool-worker-3]
filter: 2 [ForkJoinPool.commonPool-worker-1]
filter: 0 [ForkJoinPool.commonPool-worker-3]
filter: 3 [ForkJoinPool.commonPool-worker-2]
filter: 8 [main]
filter: 7 [ForkJoinPool.commonPool-worker-2]
filter: 9 [ForkJoinPool.commonPool-worker-2]
map: 0 [ForkJoinPool.commonPool-worker-3]
map: 2 [ForkJoinPool.commonPool-worker-1]
map: 8 [main]`
Run Code Online (Sandbox Code Playgroud)
正如我们所看到的,每个long的每个任务序列都由同一个线程执行.这是我们可以依赖的东西,还是巧合?执行期间线程可以"共享"任务吗?
这可能是一个已经问过的问题,但我找不到我需要的答案.
我有一个像对象一样的Set
public class MyObject {
private LocalDate dateBeginning;
private LocalDate dateEnd;
public boolean overlap(MyObject otherDate) { /*code to check overlapping*/ }
}
Run Code Online (Sandbox Code Playgroud)
我需要检查Set是否包含彼此重叠的元素.在"old-java"中,我将通过该集合两次并检查所有存在的组合,然后在找到它时中断或返回.
我们如何在Java 8中使用流和lambdas来做到这一点?
我已经试过了reduction(),filter()但它们似乎都没有用
.filter((obj1, obj2) -> { if (obj1.overlap(obj2)) return true;}) //doesn't work
Run Code Online (Sandbox Code Playgroud) 我有一系列发票:
class Invoice {
int month;
BigDecimal amount
}
Run Code Online (Sandbox Code Playgroud)
我想合并这些发票,因此我每月收到一张发票,金额是本月发票金额的总和.
例如:
invoice 1 : {month:1,amount:1000}
invoice 2 : {month:1,amount:300}
invoice 3 : {month:2,amount:2000}
Run Code Online (Sandbox Code Playgroud)
输出:
invoice 1 : {month:1,amount:1300}
invoice 2 : {month:2,amount:2000}
Run Code Online (Sandbox Code Playgroud)
我怎么能用java 8流做到这一点?
编辑:因为我的Invoice类是可变的,修改它们不是问题,我选择了Eugene的解决方案
Collection<Invoice> invoices = list.collect(Collectors.toMap(Invoice::getMonth, Function.identity(), (left, right) -> {
left.setAmount(left.getAmount().add(right.getAmount()));
return left;
})).values();
Run Code Online (Sandbox Code Playgroud) 我需要一个Java流操作来测试两个集合是否至少具有3个公共元素。
这是我的Java 7代码,可以正常工作:
@Test
public void testContainement(){
Set<Integer> setOne = IntStream.of(0,1,4,3)
.boxed()
.collect(Collectors.toCollection(HashSet::new));
Set<Integer> setTwo = IntStream.of(0,1,4,5)
.boxed()
.collect(Collectors.toCollection(HashSet::new));
Assertions.assertEquals(true,testSets(setOne,setTwo));
}
private boolean testSets( Set<Integer> setOne, Set<Integer> setTwo ) {
int counter=0;
for (int x: setOne){
if (setTwo.contains(x))
counter++;
}
return counter > 2;
}
Run Code Online (Sandbox Code Playgroud)
我们如何使用Java流操作来做到这一点?
我有这个:
Stream<CompletableFuture<List<Item>>>
Run Code Online (Sandbox Code Playgroud)
我怎样才能将它转换为
Stream<CompletableFuture<Item>>
Run Code Online (Sandbox Code Playgroud)
其中:第二个流由第一个流中每个列表内的每个项目组成。
我研究了一下thenCompose,但这解决了一个完全不同的问题,也称为“扁平化”。
如何以流方式高效地完成此操作,而不阻塞或过早消耗不必要的流项目?
这是迄今为止我最好的尝试:
ExecutorService pool = Executors.newFixedThreadPool(PARALLELISM);
Stream<CompletableFuture<List<IncomingItem>>> reload = ... ;
@SuppressWarnings("unchecked")
CompletableFuture<List<IncomingItem>> allFutures[] = reload.toArray(CompletableFuture[]::new);
CompletionService<List<IncomingItem>> queue = new ExecutorCompletionService<>(pool);
for(CompletableFuture<List<IncomingItem>> item: allFutures) {
queue.submit(item::get);
}
List<IncomingItem> THE_END = new ArrayList<IncomingItem>();
CompletableFuture<List<IncomingItem>> ender = CompletableFuture.allOf(allFutures).thenApply(whatever -> {
queue.submit(() -> THE_END);
return THE_END;
});
queue.submit(() -> ender.get());
Iterable<List<IncomingItem>> iter = () -> new Iterator<List<IncomingItem>>() {
boolean checkNext = true;
List<IncomingItem> next = null;
@Override
public boolean hasNext() {
if(checkNext) {
try { …Run Code Online (Sandbox Code Playgroud) java parallel-processing concurrency java-stream completable-future
我正在尝试重构一些代码以返回可选列表而不是可选。
我的班级有以下清单
private final List<Mapper<? extends Message>> mappers;
Run Code Online (Sandbox Code Playgroud)
有一个私有方法可以为这些映射器创建特征并返回消息列表
private List<Message> mapToFeature() {
mappers.stream()
.map(mapper -> mapper.createFeature())
.collect(Optionals.toList());
}
Run Code Online (Sandbox Code Playgroud)
Mapper 的界面如下所示:
public interface Mapper<T extends Message> {
Optional<T> createFeature();
}
Run Code Online (Sandbox Code Playgroud)
该Optionals.toList()方法返回一个收集器以将当前选项过滤到列表中。
我想更改接口(以及所有相应的类)以返回可选列表
public interface Mapper<T extends Message> {
List<Optional<T>> createFeature();
}
Run Code Online (Sandbox Code Playgroud)
我在Options util 中没有方法从多个列表中过滤当前选项。我如何能够在不对 util 类进行任何更改的情况下执行相同的操作?
java ×10
java-stream ×10
java-8 ×7
collectors ×1
concurrency ×1
lambda ×1
set ×1
sorted ×1
stateful ×1