我想转换List<CompletableFuture<X>>成CompletableFuture<List<T>>.这非常有用,因为当您有许多异步任务并且需要获得所有异步任务的结果时.
如果其中任何一个失败,则最终的未来将失败.这就是我实施的方式:
public static <T> CompletableFuture<List<T>> sequence2(List<CompletableFuture<T>> com, ExecutorService exec) {
if(com.isEmpty()){
throw new IllegalArgumentException();
}
Stream<? extends CompletableFuture<T>> stream = com.stream();
CompletableFuture<List<T>> init = CompletableFuture.completedFuture(new ArrayList<T>());
return stream.reduce(init, (ls, fut) -> ls.thenComposeAsync(x -> fut.thenApplyAsync(y -> {
x.add(y);
return x;
},exec),exec), (a, b) -> a.thenCombineAsync(b,(ls1,ls2)-> {
ls1.addAll(ls2);
return ls1;
},exec));
}
Run Code Online (Sandbox Code Playgroud)
要运行它:
ExecutorService executorService = Executors.newCachedThreadPool();
Stream<CompletableFuture<Integer>> que = IntStream.range(0,100000).boxed().map(x -> CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep((long) (Math.random() * 10));
} catch (InterruptedException e) {
e.printStackTrace(); …Run Code Online (Sandbox Code Playgroud) 我的确切方案是批量插入数据库,所以我想累积DOM对象然后每1000个,刷新它们.
我通过将代码放入累加器来检测丰满度然后刷新来实现它,但这似乎是错误的 - 刷新控件应该来自调用者.
我可以将流转换为List然后以迭代方式使用subList,但这似乎也很笨拙.
有一个简洁的方法来处理每n个元素然后继续流,而只处理流一次?
哦,那些棘手的Java 8流与lambdas.它们非常强大,但错综复杂需要一点点围绕它的所有.
假设我有User一个属性类型User.getName().假设我有一个Map<String, User>与名称相关联的用户的地图(例如,登录用户名).让我们进一步说,我有一个比较器的实例UserNameComparator.INSTANCE来排序用户名(可能与花哨的合作者等).
那么如何获取地图中的用户列表,按用户名排序?我可以忽略地图键并执行此操作:
return userMap.values()
.stream()
.sorted((u1, u2) -> {
return UserNameComparator.INSTANCE.compare(u1.getName(), u2.getName());
})
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
但是,我必须提取名称以使用的那一行UserNameComparator.INSTANCE似乎太多的手工工作.有什么方法我可以简单地提供User::getName一些映射函数,只是为了排序,并仍然将User实例返回到收集列表中?
额外奖励:如果我想要排序的东西是两个层次,如User.getProfile().getUsername()?
我正在使用Twitter4J.但我问的问题更为笼统.我想访问给定推文的用户ID.目前,我有以下两种选择:
//Option 1
stream.map(status -> status.getUser().getId())
.forEach(System.out::println);
//Option 2:
stream.map(Status::getUser)
.map(User:getId)
.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
我不喜欢第一个选项中的lambda表达式,也不想在第二个选项中强制调用两个maps.有没有办法建立一系列方法参考?我知道这Status::getUser::getId不起作用,但我想知道是否有替代品.
假设我有一串字符串.
final Stream<String> stream = ...;
Run Code Online (Sandbox Code Playgroud)
我想在修剪后过滤掉每个空字符串.
stream
.filter(Objects::nonNull)
.map(String::trim)
.filter(v -> !v.isEmpty());
Run Code Online (Sandbox Code Playgroud)
有没有办法应用Predicate#negate()替换v -> !v.isEmpty()部分?
.filter(((Predicate) String::isEmpty).negate()) // not compile
Run Code Online (Sandbox Code Playgroud) 假设我有一个给定名称,姓氏对的地图,我想找到该地图中第一个条目的名称,该名称的姓氏与某个值相匹配.我们如何以java 8的方式做到这一点.
在我下面的测试用例中,我提出了两种方法.
然而,第一个(寻找姓氏为"Donkey"的第一个人的名字)将抛出java.util.NoSuchElementException:没有值存在,因此它不安全.
第二个工作,但它不仅难以阅读,但它有点不太实用.
只是不知道是否有人在这里会建议我实现这个要么使用一个更简单更清晰的方式stream()或forEach()或两者兼而有之.
@Test
public void shouldBeAbleToReturnTheKeyOfTheFirstMatchingValue() throws Exception {
Map<String, String> names = new LinkedHashMap<>();
names.put("John", "Doe");
names.put("Fred", "Flintstone");
names.put("Jane", "Doe");
String keyOfTheFirst = names.entrySet().stream().filter(e -> e.getValue().equals("Doe")).findFirst().get().getKey();
assertEquals("John", keyOfTheFirst);
try {
names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst().get();
} catch (NoSuchElementException e){
// Expected
}
Optional<Map.Entry<String, String>> optionalEntry = names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst();
keyOfTheFirst = optionalEntry.isPresent() ? optionalEntry.get().getKey() : null;
assertNull(keyOfTheFirst);
}
Run Code Online (Sandbox Code Playgroud)
先感谢您.
我已经创建了计算字母表中每个字符的方法.我正在学习流(函数式编程)并尝试尽可能多地使用它们,但在这种情况下我不知道该怎么做:
private Map<Character, Integer> numerateAlphabet(List<Character> alphabet) {
Map<Character, Integer> m = new HashMap<>();
for (int i = 0; i < alphabet.size(); i++)
m.put(alphabet.get(i), i);
return m;
}
Run Code Online (Sandbox Code Playgroud)
那么,如何使用Java 8流重写它呢?
要按升序对其进行排序,我可以使用:
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Run Code Online (Sandbox Code Playgroud)
我怎么能按降序排列呢?
我挣扎着定义和使用
Stream.collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
Run Code Online (Sandbox Code Playgroud)
Java 8中的方法.
方法签名包括BiConsumer类型参数.BiConsumer FunctionalInterface定义了一个函数方法accept(Object,Object).据我所知,我现在可以使用任何与此功能接口一致的 lambda表达式.
但是Stream.collect JavaDoc中提到的示例是例如
List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
Run Code Online (Sandbox Code Playgroud)
我不明白为什么ArrayList.add(E e)(单个参数)与BiConsumer.accept(T t,U u)方法(两个参数)一致,并且可以用作collect方法中的累加器函数.
如你所见,我显然缺乏理解并欣赏任何解释.
我String和HashMap像下面的代码:
Map<String, String> map = new HashMap<>();
map.put("ABC", "123");
String test = "helloABC";
map.forEach((key, value) -> {
test = test.replaceAll(key, value);
});
Run Code Online (Sandbox Code Playgroud)
我尝试用HashMap值替换字符串,但这不起作用,因为test是最终的,不能在正文中重新分配forEach.
那么,有没有任何解决方案,以取代String与HashMap使用Java 8个流API?
java ×10
java-8 ×10
java-stream ×6
lambda ×5
sorting ×2
chunking ×1
concurrency ×1
hashmap ×1
optional ×1
predicate ×1