Skip to content

Commit 029139c

Browse files
committed
Demo202210Test with some demos, more tests, extra API for demos
1 parent 60be031 commit 029139c

File tree

12 files changed

+654
-16
lines changed

12 files changed

+654
-16
lines changed

jOOL-java-8/src/main/java/org/jooq/lambda/Loops.java

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.jooq.lambda.tuple.Tuple4;
44

55
import java.util.Arrays;
6+
import java.util.Iterator;
67
import java.util.LongSummaryStatistics;
78
import java.util.function.IntConsumer;
89
import java.util.function.IntUnaryOperator;
@@ -118,9 +119,10 @@ public static Tuple4<Long, LongSummaryStatistics, Exception, String> loopMeasure
118119
}
119120

120121

121-
public static class Incrementer {
122+
public static class Incrementer implements Cloneable, Iterable<Incrementer> {
122123
protected final int[] indexes;
123124
private final IntUnaryOperator maxForIndex;
125+
protected long count;
124126

125127
/** All indexes have the same max and rotate in range [0..maxExclusive)
126128
@param degree size of index vector = how many nested for-loops
@@ -161,8 +163,24 @@ public int maxAt (int indexIndex) {
161163
return maxForIndex.applyAsInt(indexIndex);
162164
}
163165

166+
public long getCount () {
167+
return count;
168+
}
169+
170+
164171
@Override public String toString () {
165-
return "Incrementer"+ Arrays.toString(indexes);
172+
return "Incrementer"+ Arrays.toString(indexes) +" @ "+getCount();
173+
}
174+
175+
176+
private Incrementer (int[] indexes, IntUnaryOperator maxForIndex) {
177+
this.indexes = indexes;
178+
this.maxForIndex = maxForIndex;
179+
}//new
180+
181+
@SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
182+
@Override protected Incrementer clone () {
183+
return new Incrementer(indexes.clone(), maxForIndex);
166184
}
167185

168186

@@ -175,10 +193,9 @@ Increments index vector (array with indexes) by 1.
175193
@see #forLoop(Predicate)
176194
*/
177195
public boolean incrementIndexVector () {
178-
final int len = indexes.length;
179-
180-
for (int i = 0; i < len; ) {
181-
if (++indexes[i] < maxForIndex.applyAsInt(i)) {
196+
count++;
197+
for (int i = 0, len = indexes.length; i < len; ) {
198+
if (++indexes[i] < maxAt(i)) {
182199
return false;
183200

184201
} else {// overflow
@@ -206,6 +223,48 @@ public boolean forLoop (Predicate<Incrementer> loopBody) {
206223
}
207224
}
208225
}
226+
227+
228+
public int[] toArray () {
229+
return indexes.clone();
230+
}
231+
232+
public Integer[] toIntegerArray () {
233+
final int len = indexes.length;
234+
Integer[] r = new Integer[len];
235+
236+
for (int i = 0; i < len; i++) {
237+
r[i] = indexes[i];
238+
}
239+
return r;
240+
}
241+
242+
243+
@Override public Iterator<Incrementer> iterator () {
244+
return new Iterator<Incrementer>() {
245+
final Incrementer snapshot = Incrementer.this.clone();
246+
boolean hasNext = true;
247+
248+
@Override public boolean hasNext () {
249+
return hasNext;
250+
}
251+
252+
@Override public Incrementer next () {
253+
boolean overflow = snapshot.incrementIndexVector();
254+
hasNext = !overflow;
255+
256+
return snapshot;
257+
}
258+
259+
@Override public String toString () {
260+
return "Iterator."+ snapshot + (hasNext? " >":" #");
261+
}
262+
};
263+
}
264+
265+
public Seq<Incrementer> seq () {
266+
return Seq.seq(this);
267+
}
209268
}//Incrementer
210269

211270
}

jOOL-java-8/src/main/java/org/jooq/lambda/Seq.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9941,4 +9941,11 @@ default void print(PrintWriter writer) {
99419941
default void print(PrintStream stream) {
99429942
forEach(stream::println);
99439943
}
9944+
9945+
9946+
/**
9947+
@see Collectable#toList
9948+
see Stream#toList
9949+
*/
9950+
List<T> toList (); // makes IDEA and Error-Prone happy
99449951
}

jOOL-java-8/src/main/java/org/jooq/lambda/Wrap.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,28 @@
2828
import org.jooq.lambda.function.Function3;
2929
import org.jooq.lambda.function.Predicate2;
3030
import org.jooq.lambda.function.Predicate3;
31+
import org.jooq.lambda.tuple.Tuple;
32+
import org.jooq.lambda.tuple.Tuple0;
33+
import org.jooq.lambda.tuple.Tuple1;
34+
import org.jooq.lambda.tuple.Tuple10;
35+
import org.jooq.lambda.tuple.Tuple11;
36+
import org.jooq.lambda.tuple.Tuple12;
37+
import org.jooq.lambda.tuple.Tuple13;
38+
import org.jooq.lambda.tuple.Tuple14;
39+
import org.jooq.lambda.tuple.Tuple15;
40+
import org.jooq.lambda.tuple.Tuple16;
41+
import org.jooq.lambda.tuple.Tuple2;
42+
import org.jooq.lambda.tuple.Tuple3;
43+
import org.jooq.lambda.tuple.Tuple4;
44+
import org.jooq.lambda.tuple.Tuple5;
45+
import org.jooq.lambda.tuple.Tuple6;
46+
import org.jooq.lambda.tuple.Tuple7;
47+
import org.jooq.lambda.tuple.Tuple8;
48+
import org.jooq.lambda.tuple.Tuple9;
3149

3250
import java.io.IOException;
3351
import java.io.UncheckedIOException;
52+
import java.util.Arrays;
3453
import java.util.concurrent.Callable;
3554
import java.util.function.BiFunction;
3655
import java.util.function.BiPredicate;
@@ -101,6 +120,13 @@ private Wrap () {}
101120
*/
102121
public static final Consumer<Throwable> PRINT_STACK_TRACE = Throwable::printStackTrace;
103122

123+
/**
124+
Can be used in tests:
125+
Thread.currentThread().setUncaughtExceptionHandler(Wrap.LOGGING_UNCAUGHT_EXCEPTION_HANDLER);
126+
Thread.setDefaultUncaughtExceptionHandler(Wrap.LOGGING_UNCAUGHT_EXCEPTION_HANDLER);
127+
*/
128+
public static final Thread.UncaughtExceptionHandler LOG_WARN_UNCAUGHT_EXCEPTION_HANDLER = LOGGER;
129+
104130
// Safe
105131

106132
public static final Predicate2<Object,Throwable> P1_SILENT_IGNORE_ALL_FALSE = (a,t) -> silentIgnoreAll(t, false);
@@ -168,6 +194,34 @@ public static <T> T cast (Class<? super T> toClazz, Object safer) throws ClassCa
168194
return (T) toClazz.cast(safer);
169195
}
170196

197+
198+
@SuppressWarnings({"unchecked", "rawtypes"})
199+
public static <T extends Tuple> T tuple (Object... v) {
200+
if (v == null || v.length == 0) {
201+
return (T) new Tuple0();
202+
}
203+
switch (v.length) {
204+
case 1: return (T) new Tuple1(v[0]);
205+
case 2: return (T) new Tuple2(v[0],v[1]);
206+
case 3: return (T) new Tuple3(v[0],v[1],v[2]);
207+
case 4: return (T) new Tuple4(v[0],v[1],v[2],v[3]);
208+
case 5: return (T) new Tuple5(v[0],v[1],v[2],v[3],v[4]);
209+
case 6: return (T) new Tuple6(v[0],v[1],v[2],v[3],v[4],v[5]);
210+
case 7: return (T) new Tuple7(v[0],v[1],v[2],v[3],v[4],v[5],v[6]);
211+
case 8: return (T) new Tuple8(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]);
212+
case 9: return (T) new Tuple9(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]);
213+
case 10: return(T)new Tuple10(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]);
214+
case 11: return(T)new Tuple11(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]);
215+
case 12: return(T)new Tuple12(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]);
216+
case 13: return(T)new Tuple13(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]);
217+
case 14: return(T)new Tuple14(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]);
218+
case 15: return(T)new Tuple15(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]);
219+
case 16: return(T)new Tuple16(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]);
220+
default: throw new IllegalArgumentException("Unknown Tuple degree: "+v.length+" "+ Arrays.toString(v));
221+
}
222+
}
223+
224+
171225
/** Same as {@link #handleInterruptedException(Throwable)}, but without casting.
172226
Will be automatically used in "catch (InterruptedException e)" */
173227
public static void handleInterruptedException (InterruptedException ie) {
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package org.jooq.lambda;
2+
3+
import org.jooq.lambda.fi.lang.SafeRunnable;
4+
import org.jooq.lambda.function.GenericPredicate;
5+
import org.jooq.lambda.function.Predicate3;
6+
import org.junit.Test;
7+
8+
import java.io.IOException;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.nio.file.Paths;
12+
import java.util.Arrays;
13+
import java.util.List;
14+
import java.util.concurrent.CountDownLatch;
15+
import java.util.concurrent.ExecutorService;
16+
import java.util.concurrent.Executors;
17+
import java.util.stream.Stream;
18+
19+
import static java.nio.charset.StandardCharsets.*;
20+
import static java.nio.file.StandardOpenOption.CREATE;
21+
import static org.junit.Assert.*;
22+
23+
public class Demo202210Test {
24+
25+
@Test
26+
public void wrapFunctionsAreFun () {
27+
final String tempDir = "/temp";
28+
29+
// 1. create vol0.txt - vol2.txt files with text lines in temp
30+
Loops.forLoop(3, Unchecked.intConsumer(
31+
(i)->{
32+
Path file = Paths.get(tempDir, "vol" + i + ".txt");
33+
34+
Stream<CharSequence> dataGen = Seq.range(1, 101).map(n -> "vol " + i + " line " + n);
35+
36+
Files.write(file, dataGen::iterator, UTF_8, CREATE);
37+
38+
}, Wrap.LOG_WARN // Exceptions - if any - go to log
39+
));
40+
41+
// 2. create empty file (Exceptions - if any - go to log)
42+
Wrap.run(()-> Files.createFile(Paths.get(tempDir, "empty.text")));
43+
44+
List<String> linesFromFiles = Seq.of("vol0", "vol1", "vol2", "empty", "none", "////:::")
45+
.map((s)->s+".txt")
46+
.map(Wrap.function(f->Paths.get(tempDir, f)))// InvalidPathException
47+
.filter(Wrap.predicate(p->p.isPresent() && Files.isRegularFile(p.v1) && Files.size(p.v1)>10))// Exception→log, returns false
48+
.map(Either::v1)
49+
.map(Wrap.function(p->Files.lines(p, UTF_8)))// seq of Either with lines
50+
.filter(Either::isPresent)
51+
// .flatMap(Either::stream)
52+
.flatMap(Either::v1)
53+
.toList();
54+
55+
assertEquals(3*100, linesFromFiles.size());
56+
assertEquals("vol 0 line 1", linesFromFiles.get(0));
57+
assertEquals("vol 2 line 100", linesFromFiles.get(linesFromFiles.size()-1));
58+
59+
int size = 1492-200+(System.lineSeparator().length())*100;
60+
Either<Long> sz = Wrap.call(() -> Files.size(Paths.get(tempDir, "vol0.txt")));
61+
assertTrue(sz.isSuccess());
62+
assertEquals(size, sz.v1.intValue());
63+
}
64+
65+
66+
@Test
67+
public void safeRunnable () {
68+
ExecutorService executor = Executors.newCachedThreadPool();
69+
70+
Thread.setDefaultUncaughtExceptionHandler(Wrap.LOG_WARN_UNCAUGHT_EXCEPTION_HANDLER);
71+
72+
CountDownLatch startSignal = new CountDownLatch(1);
73+
74+
SafeRunnable r = new SafeRunnable() { // can be implemented
75+
@Override public void execute () throws Throwable {
76+
Thread.currentThread().setUncaughtExceptionHandler(Wrap.LOG_WARN_UNCAUGHT_EXCEPTION_HANDLER);
77+
78+
startSignal.await();
79+
throw new IOException("Try to kill Executor");
80+
}
81+
};
82+
83+
Loops.loop(10, ()->executor.execute(r));
84+
85+
startSignal.countDown();
86+
87+
Wrap.run(()->Thread.sleep(1000));
88+
89+
executor.shutdownNow();
90+
}
91+
92+
93+
@Test public void testPredicate () {
94+
Predicate3<Integer,Integer,Integer> condition1 = (a,b,c)->c==b*b && b == a*a;
95+
96+
Loops.Incrementer looper = new Loops.Incrementer(3, 100);
97+
98+
long sz = looper.seq()
99+
.map(Loops.Incrementer::toIntegerArray)
100+
.filter(array -> GenericPredicate.testDynamicPredicateVarArgs(condition1, (Object[])array))
101+
.peek(array -> System.out.println(Arrays.toString(array)))
102+
.count();
103+
assertEquals(4, sz);
104+
105+
sz = looper.seq()
106+
.map(Loops.Incrementer::toIntegerArray)
107+
.map(Wrap::tuple)
108+
.filter(t -> condition1.test(Wrap.castUnsafe(t)))
109+
.peek(System.out::println)
110+
.count();
111+
assertEquals(4, sz);
112+
}
113+
114+
}

jOOL-java-8/src/test/java/org/jooq/lambda/LoopsTest.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import java.util.ArrayList;
77
import java.util.Arrays;
8+
import java.util.Iterator;
89
import java.util.List;
910
import java.util.LongSummaryStatistics;
1011
import java.util.concurrent.atomic.AtomicLong;
@@ -206,7 +207,7 @@ public LongSummaryStatisticsP () {}//new
206207
}
207208
}
208209
}
209-
assertEquals("Incrementer[0, 0, 0]", x.toString());
210+
assertEquals("Incrementer[0, 0, 0] @ 100000", x.toString());
210211
assertEquals(200, x.maxAt(0));
211212
assertEquals(50, x.maxAt(1));
212213
max[2] = 42;
@@ -265,4 +266,41 @@ public LongSummaryStatisticsP () {}//new
265266
}
266267

267268

269+
@Test
270+
public void testIncrementerFunc () {
271+
Loops.Incrementer x = new Loops.Incrementer(2, 2);
272+
assertEquals("Incrementer[0, 0] @ 0", x.toString());
273+
274+
x.incrementIndexVector();//common state
275+
assertEquals("Incrementer[1, 0] @ 1", x.toString());
276+
277+
Iterator<Loops.Incrementer> it1 = x.iterator();// start independent snapshot
278+
assertEquals("Iterator.Incrementer[1, 0] @ 0 >", it1.toString());
279+
it1.next();
280+
assertEquals("Iterator.Incrementer[0, 1] @ 1 >", it1.toString());
281+
282+
Iterator<Loops.Incrementer> it2 = x.iterator();//continue independently, but from this place
283+
assertEquals("Iterator.Incrementer[1, 0] @ 0 >", it2.toString());
284+
285+
it1.next();
286+
assertEquals("Iterator.Incrementer[1, 1] @ 2 >", it1.toString());
287+
it2.next();
288+
assertEquals("Iterator.Incrementer[0, 1] @ 1 >", it2.toString());
289+
x.incrementIndexVector();
290+
assertEquals("Incrementer[0, 1] @ 2", x.toString());
291+
292+
it1.next();
293+
assertEquals("Iterator.Incrementer[0, 0] @ 3 #", it1.toString());
294+
it2.next();
295+
assertEquals("Iterator.Incrementer[1, 1] @ 2 >", it2.toString());
296+
x.incrementIndexVector();
297+
assertEquals("Incrementer[1, 1] @ 3", x.toString());
298+
299+
it1.next();
300+
assertEquals("Iterator.Incrementer[1, 0] @ 4 >", it1.toString());
301+
it2.next();
302+
assertEquals("Iterator.Incrementer[0, 0] @ 3 #", it2.toString());
303+
x.incrementIndexVector();
304+
assertEquals("Incrementer[0, 0] @ 4", x.toString());
305+
}
268306
}

0 commit comments

Comments
 (0)