-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExample168.java
More file actions
341 lines (302 loc) · 11.8 KB
/
Example168.java
File metadata and controls
341 lines (302 loc) · 11.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
// Example 168 from page 135
//
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.IntSupplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
class Example168 {
public static void main(String[] args) {
createExample168();
System.out.println("Using Stream.forEach(...):");
Stream<String> ss = Stream.of("Hoover", "Roosevelt", "Truman", "Eisenhower", "Kennedy");
ss.forEach(System.out::println);
System.out.println("\nUsing a Stream.iterator():");
iterationExample(Stream.of("Hoover", "Roosevelt", "Truman", "Eisenhower", "Kennedy"));
primeCountingComparison();
showPrimes();
testSequentialParallel();
System.out.println("\nCreating and printing streams or lists of prime factors:");
final int range = 10;
Stream<IntStream> factorsImp = factorsImperative(range),
factorsFunc = factorsFunctional(range),
allFactors = allFactorExample168();
Stream<IntStream> someFactors = allFactors.limit(range);
someFactors.forEach(fs -> System.out.println(intStreamToString1(fs)));
allFactorLists().limit(range).forEach(System.out::println);
allFactorLists().limit(range).mapToInt(List::size).forEach(System.out::println);
System.out.println("\nStatistics on lists of prime factors:");
factorCollectorExamples();
// infiniteIntExample168();
}
// Creating finite streams
private static void createExample168() {
IntStream is = IntStream.of(2, 3, 5, 7, 11, 13);
String[] a = { "Hoover", "Roosevelt", "Truman", "Eisenhower", "Kennedy" };
Stream<String> presidents = Arrays.stream(a);
Collection<String> coll = new HashSet<String>();
coll.add("Denmark"); coll.add("Norway"); coll.add("Sweden");
Stream<String> countries = coll.stream();
}
// Creating infinite streams
public static void infiniteIntExample168() {
IntStream nats1 = IntStream.iterate(0, x -> x+1);
IntStream nats2 = IntStream.generate(new IntSupplier() {
private int next = 0;
public int getAsInt() { return next++; }
});
final int[] next = { 0 };
IntStream nats3 = IntStream.generate(() -> next[0]++);
nats3.forEach(i -> System.out.printf("%d ", i));
}
public static void iterationExample(Stream<String> xs) {
// for (String x : xs) // Illegal: xs does not implement Iterable<String>
// System.out.println(x);
for (Iterator<String> iter = xs.iterator(); iter.hasNext();) {
String x = iter.next();
System.out.println(x);
}
}
// Prime counting speed measurements
private static void primeCountingComparison() {
System.out.println("\nComparing prime counting performance:");
int range = 10_000_000;
System.out.printf("Counting the prime numbers in [0..%d]:%n", range);
{
Timer t = new Timer();
int count = 0;
for (int i=0; i<range; i++)
if (isPrime(i))
count++;
System.out.printf("for-loop: count = %10d, time = %10.2f ms%n", count, t.check()*1E3);
}
{
Timer t = new Timer();
long count = IntStream.range(0, range).filter(i -> isPrime(i)).count();
System.out.printf("seq stream: count = %10d, time = %10.2f ms%n", count, t.check()*1E3);
}
{
Timer t = new Timer();
long count = IntStream.range(0, range).parallel().filter(i -> isPrime(i)).count();
System.out.printf("par stream: count = %10d, time = %10.2f ms%n", count, t.check()*1E3);
}
}
// Collectors on prime factor lists of type Stream<List<Integer>>
public static void factorCollectorExamples() {
// Group integers by the number of prime factors they have, and show the groups:
Map<Integer, List<List<Integer>>> factorGroups =
allFactorLists().limit(11).collect(Collectors.groupingBy(List::size));
System.out.println(factorGroups);
// {1=[[2], [3], [5], [7], [11]], 2=[[2, 2], [2, 3], [3, 3], [2, 5]], 3=[[2, 2, 2], [2, 2, 3]]}
// Group integers by the number of prime factors they have, then
// count the number of members in each group:
Map<Integer, Long> factorGroupSizes =
allFactorLists().limit(5000).collect(Collectors.groupingBy(List::size, Collectors.counting()));
System.out.println(factorGroupSizes);
// {1=669, 2=1366, 3=1273, 4=832, 5=452, 6=224, 7=104, 8=47, 9=22, 10=7, 11=3, 12=1}
// Count the number of times 2, 3, ... appear as prime factor in a
// list of factorizations. Presumably best to flatten the factor
// lists into an IntStream and apply groupingBy and counting to that:
Map<Integer, Long> factorFrequencies =
allFactorLists().limit(11).flatMap(List::stream)
.collect(Collectors.groupingBy(x -> x, Collectors.counting()));
System.out.println(factorFrequencies);
}
// Various ways to convert an IntStream to a String with a neat list-like look
private static String intStreamToString1(IntStream is) {
return is
.mapToObj(String::valueOf)
.collect(Collectors.joining(",", "[", "]"));
}
private static String intStreamToString2(IntStream is) {
return is
.boxed()
.collect(Collectors.mapping(String::valueOf,
Collectors.joining(",", "[", "]")));
}
private static boolean isPrime(int n) {
int k = 2;
while (k * k <= n && n % k != 0)
k++;
return n >= 2 && k * k > n;
}
// Various ways to create a sequential stream of prime numbers
public static void showPrimes() {
Consumer<IntStream> print = is ->
is.limit(20).forEach(x -> System.out.printf("%d ", x));
System.out.println("Infinite stream, lazy functional generation");
print.accept(primes1());
System.out.println("\nFinite stream, lazy functional generation");
print.accept(primes2(30));
System.out.println("\nInfinite stream, lazy stateful generation");
print.accept(primes3());
System.out.println("\nFinite stream, eager imperative generation");
print.accept(primes4(30));
System.out.println();
}
// A sequential infinite stream of primes, lazily built
public static IntStream primes1() {
IntStream nats = IntStream.iterate(0, x -> x+1);
IntStream primes = nats.filter(x -> isPrime(x));
return primes;
}
// A sequential finite stream of the first n primes, lazily built
public static IntStream primes2(int n) {
return IntStream.iterate(0, x -> x+1).filter(x -> isPrime(x)).limit(n);
}
// A sequential infinite stream of the first n primes, lazily built
public static IntStream primes3() {
final int[] p = { 0 };
IntSupplier primeGenerator =
() -> {
while (!isPrime(p[0]))
p[0]++;
System.out.printf("[%d]", p[0]);
return p[0]++;
};
return IntStream.generate(primeGenerator);
}
// A sequential finite stream of the first n primes, eagerly built
public static IntStream primes4(int n) {
IntStream.Builder isb = IntStream.builder();
int p = 0, count = 0;
while (count < n) {
if (isPrime(p)) {
System.out.printf("[%d]", p);
isb.accept(p);
count++;
}
p++;
}
return isb.build();
}
// Various ways to create a stream of the set of prime factors of
// the natural numbers
public static List<Integer> factorList(int p) {
List<Integer> result = new ArrayList<Integer>();
int k = 2;
while (p >= k * k) {
if (p % k == 0) {
result.add(k);
p /= k;
} else
k++;
}
// Now p < k * k and no number in 2..k divides p
if (p > 1)
result.add(p);
return result;
}
public static IntStream factorStream(int p) {
IntStream.Builder isb = IntStream.builder();
int k = 2;
while (p >= k * k) {
if (p % k == 0) {
isb.accept(k);
p /= k;
} else
k++;
}
// Now p < k * k and no number in 2..k divides p
if (p > 1)
isb.accept(p);
return isb.build();
}
// Shows how to get from Stream<Integer> to IntStream
public static IntStream factorStreamFromList(int p) {
return factorList(p).stream().mapToInt(Integer::intValue);
}
// Finite stream of streams of prime factors, built imperatively and
// eagerly
public static Stream<IntStream> factorsImperative(int range) {
Stream.Builder<IntStream> sb = Stream.<IntStream>builder();
for (int p=2; p<range; p++)
sb.accept(factorStream(p));
return sb.build();
}
// Finite stream of streams of prime factors, built lazily
public static Stream<IntStream> factorsFunctional(int range) {
return IntStream.range(2, range).mapToObj(Example168::factorStream);
}
// Infinite stream of streams of prime factors. Seems impossible to
// make it using an IntStream.Builder, but can make it from an
// IntSupplier or more functionally, using iterate:
public static Stream<IntStream> allFactorExample168() {
IntStream allNats1 = IntStream.iterate(2, x -> x+1);
return allNats1.mapToObj(Example168::factorStream);
}
public static Stream<List<Integer>> allFactorLists() {
return IntStream.iterate(2, x -> x+1).mapToObj(Example168::factorList);
}
public static void testSequentialParallel() {
System.out.println(isSorted2(IntStream.of(2, 5, 3, 7)));
Random rnd = new Random();
// Make random sequential stream, sort it, and test it; should be true
System.out.printf("true = %b%n",
isSorted2(rnd.ints(100000).sorted()));
// Make random parallel stream, sort it, and test it; most likely false
System.out.printf("false = %b%n",
isSorted2(rnd.ints(100000).parallel().sorted()));
// Make random parallel stream, sort it, make it sequential, and test it; should be true
System.out.printf("true = %b%n",
isSorted2(rnd.ints(100000).parallel().sorted().sequential()));
// Make increasing sequential stream and test it; should be true
System.out.printf("true = %b%n",
isSorted2(IntStream.range(1,100000)));
// Make increasing parallel stream and test it; most likely false
System.out.printf("false = %b%n",
isSorted2(IntStream.range(1,100000).parallel()));
// Make increasing parallel stream, multiply by 2 in parallel,
// then sequentialize and test it; should be true
System.out.printf("true = %b%n",
isSorted2(IntStream.range(1,100000).parallel().map(x -> 2 * x).sequential()));
}
// Various ways to test sortedness of an IntStream
// This abomination works, on a sequential stream, not a parallel one
static boolean isSorted1(IntStream xs) {
final int[] last = new int[1];
last[0] = Integer.MIN_VALUE;
try {
xs.forEach(x -> {
if (last[0] > x)
throw new RuntimeException();
else
last[0] = x;
});
} catch (RuntimeException exn) {
return false;
}
return true;
}
// This should work for sequential streams, although the predicate
// is stateful.
static boolean isSorted2(IntStream xs) {
final int[] last = { Integer.MIN_VALUE };
return xs.allMatch(x -> { int old = last[0]; last[0] = x; return old <= x; } );
}
// This should work for sequential streams, although the predicate
// is stateful. Note the daring exploitation of Java left-to-right
// evaluation in the predicate.
static boolean isSorted3(IntStream xs) {
final int[] last = { Integer.MIN_VALUE };
return xs.allMatch(x -> last[0] <= (last[0] = x));
}
// Simple timer, measuring wall-clock (elapsed) time in seconds
private static class Timer {
private long start;
public Timer() {
start = System.nanoTime();
}
public double check() {
return (System.nanoTime() - start)/1e9;
}
}
}