Skip to content

Commit a1b0a0b

Browse files
committed
feat(CompletableFutures): add new methods
1 parent b8ccbe0 commit a1b0a0b

3 files changed

Lines changed: 117 additions & 5 deletions

File tree

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.github.lokic</groupId>
88
<artifactId>java-plus</artifactId>
9-
<version>0.0.5</version>
9+
<version>0.0.6</version>
1010
<name>java-plus</name>
1111
<description>Provide some useful extensions on the basis of core java to make java more usable.</description>
1212
<url>https://github.com/lokic/java-plus</url>

src/main/java/com/github/lokic/javaplus/CompletableFutures.java

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,74 @@
66
import com.github.lokic.javaplus.func.function.Function5;
77
import com.github.lokic.javaplus.func.tuple.*;
88
import com.github.lokic.javaplus.tuple.*;
9+
import lombok.SneakyThrows;
910

1011
import java.util.List;
1112
import java.util.Map;
13+
import java.util.concurrent.Callable;
1214
import java.util.concurrent.CompletableFuture;
15+
import java.util.concurrent.ExecutionException;
1316
import java.util.function.Function;
17+
import java.util.function.Supplier;
1418

1519
public class CompletableFutures {
1620

1721
public static <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futures) {
18-
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]))
22+
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
1923
.thenApply(v -> futures.stream().map(CompletableFuture::join).collect(java.util.stream.Collectors.<T>toList()));
2024
}
2125

2226
public static <K, V> CompletableFuture<Map<K, V>> sequence(Map<K, CompletableFuture<V>> futures) {
23-
return CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[futures.size()]))
27+
return CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0]))
2428
.thenApply(v -> futures.entrySet().stream().collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, e -> e.getValue().join())));
2529
}
2630

31+
public static <T> CompletableFuture<T> supply(Supplier<T> supplier) {
32+
CompletableFuture<T> future = new CompletableFuture<>();
33+
try {
34+
T data = supplier.get();
35+
future.complete(data);
36+
} catch (Throwable ex) {
37+
future.completeExceptionally(ex);
38+
}
39+
return future;
40+
}
41+
42+
public static <T> CompletableFuture<T> call(Callable<T> callable) {
43+
CompletableFuture<T> future = new CompletableFuture<>();
44+
try {
45+
T data = callable.call();
46+
future.complete(data);
47+
} catch (Throwable ex) {
48+
future.completeExceptionally(ex);
49+
}
50+
return future;
51+
}
52+
53+
54+
@SneakyThrows
55+
public static <T> T getOrElseSneakyThrow(CompletableFuture<T> future) {
56+
try {
57+
return future.get();
58+
} catch (ExecutionException e) {
59+
throw e.getCause();
60+
}
61+
}
62+
63+
public static <T> T getOrElseThrow(CompletableFuture<T> future) throws Throwable {
64+
return getOrElseThrow(future, Function.identity());
65+
}
66+
67+
public static <T, X extends Throwable> T getOrElseThrow(CompletableFuture<T> future, Function<? super Throwable, X> exceptionProvider) throws X {
68+
try {
69+
return future.get();
70+
} catch (ExecutionException e) {
71+
throw exceptionProvider.apply(e.getCause());
72+
} catch (Throwable e) {
73+
throw exceptionProvider.apply(e);
74+
}
75+
}
76+
2777
public static class Fors {
2878

2979
private Fors() {
@@ -34,7 +84,6 @@ public static <T1, T2> Function<T1, CompletableFuture<Tuple2<T1, T2>>> For(Funct
3484
return t1 -> f.apply(t1).thenApply(t2 -> Tuple.of(t1, t2));
3585
}
3686

37-
3887
public static <T1, T2, T3> Function<Tuple2<T1, T2>, CompletableFuture<Tuple3<T1, T2, T3>>> For(Function2<T1, T2, CompletableFuture<T3>> f) {
3988
return t -> f.apply(t.getT1(), t.getT2()).thenApply(t3 -> Tuple.of(t.getT1(), t.getT2(), t3));
4089
}
@@ -51,7 +100,6 @@ public static <T1, T2, T3, T4, T5, T6> Function<Tuple5<T1, T2, T3, T4, T5>, Comp
51100
return t -> f.apply(t.getT1(), t.getT2(), t.getT3(), t.getT4(), t.getT5()).thenApply(t6 -> Tuple.of(t.getT1(), t.getT2(), t.getT3(), t.getT4(), t.getT5(), t6));
52101
}
53102

54-
55103
public static <T1, R> Function<T1, R> Yield(Function<T1, R> f) {
56104
return f;
57105
}

src/test/java/com/github/lokic/javaplus/CompletableFuturesTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,42 @@
11
package com.github.lokic.javaplus;
22

3+
import org.assertj.core.util.Lists;
34
import org.junit.Assert;
45
import org.junit.Test;
56

7+
import java.io.IOException;
8+
import java.util.ArrayList;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
612
import java.util.concurrent.CompletableFuture;
713

814
import static com.github.lokic.javaplus.CompletableFutures.Fors.For;
915
import static com.github.lokic.javaplus.CompletableFutures.Fors.Yield;
1016

1117
public class CompletableFuturesTest {
1218

19+
@Test
20+
public void test_list_sequence() {
21+
List<CompletableFuture<String>> li = new ArrayList<>();
22+
for (int i = 0; i < 5; i++) {
23+
li.add(CompletableFuture.completedFuture(String.valueOf(i)));
24+
}
25+
Assert.assertEquals(Lists.newArrayList("0", "1", "2", "3", "4"), CompletableFutures.sequence(li).join());
26+
}
27+
28+
29+
@Test
30+
public void test_map_sequence() {
31+
Map<Integer, CompletableFuture<String>> map = new HashMap<>();
32+
Map<Integer, String> expect = new HashMap<>();
33+
for (int i = 0; i < 5; i++) {
34+
map.put(i, CompletableFuture.completedFuture(String.valueOf(i)));
35+
expect.put(i, String.valueOf(i));
36+
}
37+
Assert.assertEquals(expect, CompletableFutures.sequence(map).join());
38+
}
39+
1340
@Test
1441
public void test_For_success() {
1542
CompletableFuture<String> r = CompletableFuture.completedFuture("1")
@@ -35,4 +62,41 @@ public void test_For_exception() {
3562
Assert.assertTrue(r.isCompletedExceptionally());
3663
}
3764

65+
@Test(expected = IllegalStateException.class)
66+
public void test_getOrElseSneakyThrow_exception() {
67+
CompletableFuture<String> f = new CompletableFuture<>();
68+
f.completeExceptionally(new IllegalStateException());
69+
CompletableFutures.getOrElseSneakyThrow(f);
70+
}
71+
72+
@Test(expected = IOException.class)
73+
public void test_getOrElseThrow_exception() throws Throwable {
74+
CompletableFuture<String> f = new CompletableFuture<>();
75+
f.completeExceptionally(new IOException());
76+
CompletableFutures.getOrElseThrow(f);
77+
}
78+
79+
@Test(expected = IllegalStateException.class)
80+
public void test_getOrElseThrow_exceptionProvider_exception() {
81+
CompletableFuture<String> f = new CompletableFuture<>();
82+
f.completeExceptionally(new IOException());
83+
CompletableFutures.getOrElseThrow(f, IllegalStateException::new);
84+
}
85+
86+
@Test
87+
public void test_supply() {
88+
Assert.assertEquals("123", CompletableFutures.supply(() -> "123").join());
89+
Assert.assertTrue(CompletableFutures.supply(() -> {
90+
throw new IllegalStateException();
91+
}).isCompletedExceptionally());
92+
}
93+
94+
@Test
95+
public void test_call() {
96+
Assert.assertEquals("123", CompletableFutures.call(() -> "123").join());
97+
Assert.assertTrue(CompletableFutures.call(() -> {
98+
throw new IOException();
99+
}).isCompletedExceptionally());
100+
}
101+
38102
}

0 commit comments

Comments
 (0)