package tryAny.effectiveJava;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Anagrams {
public static void main(String[] args) throws IOException {
File dictionary = new File("/application/gradle/getting-started.html");
int minGroupSize = 2;
Map<String, Set<String>> groups = new HashMap<>();
//Example 1 start
try (Scanner s = new Scanner(dictionary)) {
while (s.hasNext()) {
String word = s.next();
groups.computeIfAbsent(alphabetize(word), (unused) -> new TreeSet<>()).add(word);
}
}
for (Set<String> group : groups.values()) {
if (group.size() >= minGroupSize) {
System.out.println(group.size() + ":" + group);
}
}
//Example 1 end
//Example 2 start(This is an anagram for each line, so the result is different from Example 1.)
Path dictionary2 = Paths.get("/application/gradle/getting-started.html");
try (Stream<String> words = Files.lines(dictionary2)) {
words.collect(Collectors.groupingBy(word -> word.chars().sorted()
.collect(StringBuilder::new, (sb, c) -> sb.append((char) c), StringBuilder::append).toString()))
.values().stream().filter(group -> group.size() >= minGroupSize)
.map(group -> group.size() + ":" + group).forEach(System.out::println);
}
//Example 2 end
//Example 3 start (same result as Example 2)
try (Stream<String> words = Files.lines(dictionary2)) {
words.collect(Collectors.groupingBy(word -> alphabetize(word)))
.values().stream()
.filter(group -> group.size() >= minGroupSize)
.forEach(g -> System.out.println(g.size() + ":" + g));
}
//Example 3 end
}
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
}
package tryAny.effectiveJava;
public class CharStream {
public static void main(String[] args) {
"Hello, world!".chars().forEach(System.out::print);
//72101108108111443211911111410810033 is displayed
System.out.println();
"Hello, world!".chars().forEach(x -> System.out.print((char) x));
// Hello, world!Is displayed
}
}
When replacing an existing for loop with a stream, you should do it only when it makes sense.
The following can be done with code block (** ordinary iterative statement? **), which cannot be done with stream processing using functional objects.
Lambda expressions can read only practically final local variables, but code blocks can read and change anything.
With code block, you can return from enclosing method (** what? **), you can operate break and continue from the loop, and you can throw the declared checked exception, but with lambda expression, that's all. I can't do that.
Here's what you can easily do with stream:
Uniform element conversion
Element filtering
Processing to connect elements in a single operation (addition, minimum value, etc.)
Processing to aggregate elements into collection (grouping by certain attributes, etc.)
The process of searching for elements that meet specific criteria
It is difficult for stream to process elements in different stages of the pipeline at the same time. In the following example, a Mersenne prime number is output. A Mersenne prime number is a number represented by 2 ^ p-1 when p is a prime number, and is always a prime number. With stream processing Prime number → Mersenne prime number → Separate by 20 → Display However, in the displayed part, it is not possible to access the original prime number (although this time it was possible to calculate back from the result).
package tryAny.effectiveJava;
import static java.math.BigInteger.*;
import java.math.BigInteger;
import java.util.stream.Stream;
public class MersennePrimes {
public static void main(String[] args) {
primes().map(p -> TWO.pow(p.intValueExact()).subtract(ONE)).filter(mersenne -> mersenne.isProbablePrime(50))
.limit(20)
// .forEach(System.out::println);
.forEach(mp -> System.out.println(mp.bitLength() + ":" + mp));
}
static Stream<BigInteger> primes() {
return Stream.iterate(TWO, BigInteger::nextProbablePrime);
}
}
Recommended Posts