βμ΅λͺ ν΄λμ€λ (ν¨μν μΈν°νμ΄μ€κ° μλ) νμ μ μΈμ€ν΄μ€λ₯Ό λ§λ€ λλ§ μ¬μ©νλΌβ
// μ΅λͺ
ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό ν¨μ κ°μ²΄λ‘ μ¬μ© - λ‘μ κΈ°λ²μ΄λ€!
Collections.sort(words, new Comparator<String>() {
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
System.out.println(words);
Collections.shuffle(words);
// μ½λ 42-2 λλ€μμ ν¨μ κ°μ²΄λ‘ μ¬μ© - μ΅λͺ
ν΄λμ€ λ체
Collections.sort(words,
(s1, s2) -> Integer.compare(s1.length(), s2.length()));
System.out.println(words);
Collections.shuffle(words);
DoubleBinaryOperator
μΈν°νμ΄μ€ λ³μμ ν λΉν¨.DoubleBinaryOperator
μΈν°νμ΄μ€λ double
νμ
μΈμ 2κ°λ₯Ό λ°μ double
νμ
κ²°κ³Όλ₯Ό λ°νν¨.// ν¨μ κ°μ²΄(λλ€)λ₯Ό μΈμ€ν΄μ€ νλμ μ μ₯ν΄ μμλ³ λμμ ꡬνν μ΄κ±° νμ
public enum Operation {
PLUS ("+", (x, y) -> x + y),
MINUS ("-", (x, y) -> x - y),
TIMES ("*", (x, y) -> x * y),
DIVIDE("/", (x, y) -> x / y);
private final String symbol;
private final DoubleBinaryOperator op;
Operation(String symbol, DoubleBinaryOperator op) {
this.symbol = symbol;
this.op = op;
}
@Override public String toString() { return symbol; }
public double apply(double x, double y) {
return op.applyAsDouble(x, y);
}
}
this
ν€μλλ λ°κΉ₯ μΈμ€ν΄μ€, μ΅λͺ
ν΄λμ€μμμ this
λ μμ βλ©μλ μ°Έμ‘° μͺ½μ΄ μ§§κ³ λͺ ννλ€λ©΄ λ©μλ μ°Έμ‘°λ₯Ό μ°κ³ , κ·Έλ μ§ μμ λλ§ λλ€λ₯Ό μ¬μ©νλΌβ
// map.mergeλ₯Ό μ΄μ©ν΄ ꡬνν λΉλν - λλ€ λ°©μκ³Ό λ©μλ μ°Έμ‘° λ°©μμ λΉκ΅ν΄λ³΄μ.
public class Freq {
public static void main(String[] args) {
Map<String, Integer> frequencyTable = new TreeMap<>();
for (String s : args)
frequencyTable.merge(s, 1, (count, incr) -> count + incr); // λλ€
System.out.println(frequencyTable);
frequencyTable.clear();
for (String s : args)
frequencyTable.merge(s, 1, Integer::sum); // λ©μλ μ°Έμ‘°
System.out.println(frequencyTable);
}
}
λ©μλ μ°Έμ‘° μ ν | μμ | λλ€ νν |
---|---|---|
μ μ | Integer::parseInt | str β Integer.parseInt(str) |
νμ μ (μΈμ€ν΄μ€) | Instant.now()::isAfter | Instant then = Instant.now(); t β then.isAfter(t) |
λΉνμ μ (μΈμ€ν΄μ€) | String::toLowerCase | str β str.toLowerCase() |
ν΄λμ€ μμ±μ | TreeMap<K, V>::new | () β new TreeMap<K, V>() |
λ°°μ΄ μμ±μ | int[]::new | len β new int[len] |
β보ν΅μ
java.util.function
ν¨ν€μ§μ νμ€ ν¨μν μΈν°νμ΄μ€λ₯Ό μ¬μ©νλ κ²μ΄ κ°μ₯ μ’μ μ νβ
java.util.function
ν¨ν€μ§λ₯Ό 보면 λ€μν μ©λμ νμ€ ν¨μν μΈν°νμ΄μ€κ° λ΄κ²¨ μμ.μΈν°νμ΄μ€ | ν¨μ μκ·Έλμ² | μ | μ€λͺ |
---|---|---|---|
UnaryOperator | T apply(T t) | String::toLowerCase | λ°νκ°κ³Ό μΈμμ νμ μ΄ κ°μ ν¨μ(μΈμ 1κ°) |
BinaryOperator | T apply(T t1, T t2) | BigInteger::add | λ°νκ°κ³Ό μΈμμ νμ μ΄ κ°μ ν¨μ(μΈμ 2κ°) |
Predicate | boolean test(T t) | Collection::isEmpty | μΈμ νλλ₯Ό λ°μ booleanμ λ°ννλ ν¨μ |
Function<T, R> | R apply(T t) | Arrays::asList | μΈμμ λ°ν νμ μ΄ λ€λ₯Έ ν¨μ |
Supplier | T get() | Instance::now | μΈμλ₯Ό λ°μ§ μκ³ κ°μ λ°ν(νΉμ μ 곡)νλ ν¨μ |
Consumer | void accept(T t) | System.out::println | μΈμλ₯Ό νλ λ°κ³ λ°νκ°μ μλ(νΉν μΈμλ₯Ό μλΉνλ ) ν¨μ |
Compartor<T>
μΈν°νμ΄μ€ToIntBiFunction<T, U>
μ λμΌν¨.@FunctionalInterface
μ΄λ
Έν
μ΄μ
μ μ¬μ©νλΌ.@FunctionalInterface
μ΄λ
Έν
μ΄μ
μ κΈ°λ₯βμ€νΈλ¦Όκ³Ό λ°λ³΅ μ€ μ΄λ μͺ½μ΄ λμμ§ νμ νκΈ° μ΄λ ΅λ€λ©΄ λ λ€ ν΄λ³΄κ³ λ λμ μͺ½μ ννλΌβ
// μ€νΈλ¦Όμ μ μ ν νμ©νλ©΄ κΉλνκ³ λͺ
λ£ν΄μ§λ€.
public class HybridAnagrams {
public static void main(String[] args) throws IOException {
Path dictionary = Paths.get(args[0]);
int minGroupSize = Integer.parseInt(args[1]);
try (Stream<String> words = Files.lines(dictionary)) {
words.collect(groupingBy(word -> alphabetize(word)))
.values().stream()
.filter(group -> group.size() >= minGroupSize)
.forEach(g -> System.out.println(g.size() + ": " + g));
}
}
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
}
CharSequence
μΈν°νμ΄μ€μ chars()
λ©μλλ λ°ν κ°μ΄ IntStream
μ.final
μ΄κ±°λ μ¬μ€μ final
μΈ λ³μλ§ μ½μ μ μμ)return
, break
, continue
λ¬Έ μ¬μ©. (λλ€μμλ λΆκ°λ₯)static Stream<BigInteger> primes() { ... }
βμ€νΈλ¦Ό μ°μ°μ 건λ€λ ν¨μ κ°μ²΄λ λͺ¨λ λΆμμ©(side effect)μ΄ μμ΄μΌ νλ€β
forEach
μ°μ°μ μ’
λ¨ μ°μ° μ€ κΈ°λ₯μ΄ κ°μ₯ μ κ³ κ°μ₯ βλβ μ€νΈλ¦Όλ€μ.β forEach
μ°μ°μ μ€νΈλ¦Ό κ³μ° κ²°κ³Όλ₯Ό λ³΄κ³ ν λλ§ μ¬μ©νκ³ , κ³μ°νλ λ°λ μ°μ§ λ§μ.
java.util.stream.Collectors
μ λ©€λ²λ₯Ό μ μ μν¬νΈνμ¬ μ¬μ©ν¨.toList()
: 리μ€νΈ λ°ν// λΉλνμμ κ°μ₯ νν λ¨μ΄ 10κ°λ₯Ό λ½μλ΄λ νμ΄νλΌμΈ
List<String> topTen = freq.keySet().stream()
.sorted(comparing(freq::get).reversed())
.limit(10)
.collect(toList());
toMap(keyMapper, valueMapper)
: ν€ λ§€νΌμ κ° λ§€νΌλ₯Ό λ°μ 맡μ λ°νMap<String, Operation> stringToEnum =
Stream.of(values()).collect(
toMap(Object::toString, e -> e));
toSet()
: μ§ν© λ°νSet<String> result = givenList.stream()
.collect(toSet());
joining()
: μμλ€μ μ°κ²°νμ¬ λ¬Έμμ΄ λ°ν// 맀κ°λ³μκ° μμ κ²½μ° : "abbcccdd" μΆλ ₯
String result = givenList.stream()
.collect(joining());
// 맀κ°λ³μκ° μμ κ²½μ°(ꡬλΆλ¬Έμλ₯Ό μ°κ²°λΆμμ μ½μ
ν΄ μ€) : "a bb ccc dd" μΆλ ₯
String result = givenList.stream()
.collect(joining(" "));
groupingBy(classifier)
: λΆλ₯ ν¨μλ₯Ό 맀κ°λ³μλ‘ λ°μ μμλ€μ μΉ΄ν
κ³ λ¦¬λ³λ‘ λͺ¨μ λμ 맡μ λ΄μ μμ§κΈ° λ°ν.// κ°λ¨ν μμ : μνλ²³νν λ¨μ΄λ₯Ό μνλ²³ν κ²°κ³Όκ° κ°μ λ¨μ΄λ€μ 리μ€νΈλ‘ 맀ννλ 맡 μμ±.
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
words.collect(groupingBy(word -> alphabetize(word)));
// λΆλ₯ ν¨μμ λ€μ΄ μ€νΈλ¦Όμ λ°λ μμ
/** λ€μ΄μ€νΈλ¦Ό μμ§κΈ°λ‘ counting()μ 건λ€μ κ° μΉ΄ν
κ³ λ¦¬(ν€)λ₯Ό (μμλ₯Ό λ΄μ 컬λ μ
μ΄ μλ)
* ν΄λΉ μΉ΄ν
κ³ λ¦¬μ μνλ μμμ κ°μ(κ°)μ 맀νν 맡μ μ»μ
*/
// μ€νΈλ¦Όμ μ λλ‘ νμ©ν΄ λΉλνλ₯Ό μ΄κΈ°ννλ€.
Map<String, Long> freq;
try (Stream<String> words = new Scanner(file).tokens()) {
freq = words
.collect(groupingBy(String::toLowerCase, counting()));
}
groupingBy
λͺ
μΈstatic <T,K> Collector<T,?,Map<K,List<T>>>
groupingBy(Function<? super T,? extends K> classifier)
static <T,K,A,D> Collector<T,?,Map<K,D>>
groupingBy(Function<? super T,? extends K> classifier,
Collector<? super T,A,D> downstream)
static <T,K,D,A,M extends Map<K,D>> Collector<T,?,M>
groupingBy(Function<? super T,? extends K> classifier,
Supplier<M> mapFactory, Collector<? super T,A,D> downstream)
βμμ μνμ€λ₯Ό λ°ννλ κ³΅κ° APIμ λ°ν νμ μλ
Collection
μ΄λ κ·Έ νμ νμ μ μ°λ κ² μΌλ°μ μΌλ‘ μ΅μ β
for-each
λ‘ λ°λ³΅νκΈΈ μνλ μ¬μ©μλ λΆλ§μ ν λ‘ν κ²μ.Stream<E>
λ₯Ό Iterable<E>
λ‘ μ€κ°ν΄μ£Όλ μ΄λν°λ₯Ό μ¬μ©νλ©΄ μ€νΈλ¦Όμ for-each
λ¬ΈμΌλ‘ λ°λ³΅ν μ μμ// μ€νΈλ¦Ό <-> λ°λ³΅μ μ΄λν°
public class Adapters {
// Stream<E>λ₯Ό Iterable<E>λ‘ μ€κ°ν΄μ£Όλ μ΄λν°
public static <E> Iterable<E> iterableOf(Stream<E> stream) {
return stream::iterator;
}
// Iterable<E>λ₯Ό Stream<E>λ‘ μ€κ°ν΄μ£Όλ μ΄λν°
public static <E> Stream<E> streamOf(Iterable<E> iterable) {
return StreamSupport.stream(iterable.spliterator(), false);
}
}
Collection
μΈν°νμ΄μ€λ Iterable
μ νμ νμ
μ΄κ³ stream
λ©μλλ μ 곡νλ λ°λ³΅κ³Ό μ€νΈλ¦Όμ λμμ μ§μν¨.β μμ μνμ€λ₯Ό λ°ννλ κ³΅κ° APIμ λ°ν νμ
μλ Collection
μ΄λ κ·Έ νμ νμ
μ μ°λ κ² μΌλ°μ μΌλ‘ μ΅μ μ.
β ArrayList
λ HashSet
κ°μ νμ€ μ»¬λ μ
ꡬν체λ₯Ό λ°ννμ
β μ μ© μ»¬λ μ μ ꡬννλ λ°©μμ κ²ν ν΄λ³΄μ.
public class PowerSet {
// μ
λ ₯ μ§ν©μ λ©±μ§ν©μ μ μ© μ»¬λ μ
μ λ΄μ λ°ννλ€.
public static final <E> Collection<Set<E>> of(Set<E> s) {
List<E> src = new ArrayList<>(s);
if (src.size() > 30)
throw new IllegalArgumentException(
"μ§ν©μ μμκ° λ무 λ§μ΅λλ€(μ΅λ 30κ°).: " + s);
return new AbstractList<Set<E>>() {
@Override public int size() {
// λ©±μ§ν©μ ν¬κΈ°λ 2λ₯Ό μλ μ§ν©μ μμ μλ§νΌ κ±°λμ κ³± κ²κ³Ό κ°λ€.
return 1 << src.size();
}
@Override public boolean contains(Object o) {
return o instanceof Set && src.containsAll((Set)o);
}
@Override public Set<E> get(int index) {
Set<E> result = new HashSet<>();
for (int i = 0; index != 0; i++, index >>= 1)
if ((index & 1) == 1)
result.add(src.get(i));
return result;
}
};
}
public static void main(String[] args) {
Set s = new HashSet(Arrays.asList(args));
System.out.println(PowerSet.of(s));
}
}
contains
μ size
λ₯Ό ꡬννλ κ² λΆκ°λ₯ν λ(μ¦, 컬λ μ
μ λ°ννλ κ² λΆκ°λ₯ν λ)λ 컬λ μ
보λ€λ μ€νΈλ¦Όμ΄λ Iterable
μ λ°ννλ νΈμ΄ λ«λ€.βκ³μ°λ μ¬λ°λ‘ μννκ³ μ±λ₯λ λΉ¨λΌμ§ κ±°λΌλ νμ μμ΄λ μ€νΈλ¦Ό νμ΄νλΌμΈ λ³λ ¬νλ μλμ‘°μ°¨ νμ§ λ§λΌβ
// λ³λ ¬ μ€νΈλ¦Όμ μ¬μ©ν΄ μ²μ 20κ°μ λ©λ₯΄μΌ μμλ₯Ό μμ±νλ νλ‘κ·Έλ¨
// μ£Όμ: λ³λ ¬νμ μν₯μΌλ‘ νλ‘κ·Έλ¨μ΄ μ’
λ£νμ§ μλλ€.
public class ParallelMersennePrimes {
public static void main(String[] args) {
primes().map(p -> TWO.pow(p.intValueExact()).subtract(ONE))
.parallel() // μ€νΈλ¦Ό λ³λ ¬ν
.filter(mersenne -> mersenne.isProbablePrime(50))
.limit(20)
.forEach(System.out::println);
}
static Stream<BigInteger> primes() {
return Stream.iterate(TWO, BigInteger::nextProbablePrime);
}
}
β μ€νΈλ¦Ό λΌμ΄λΈλ¬λ¦¬κ° μ΄ νμ΄νλΌμΈμ λ³λ ¬ννλ λ°©λ²μ μ°Ύμλ΄μ§ λͺ»νκΈ° λλ¬Έ.
Stream.iterate
κ±°λ μ€κ° μ°μ°μΌλ‘ limit
λ₯Ό μ°λ©΄ νμ΄νλΌμΈ λ³λ ¬νλ‘λ μ±λ₯ κ°μ μ κΈ°λν μ μμ.β μ μ½λλ λ λ¬Έμ λ₯Ό λͺ¨λ μ§λκ³ μμ..
β μ€νΈλ¦Ό λ³λ ¬νλ μ€μ§ μ±λ₯ μ΅μ ν μλ¨μμ κΈ°μ΅νμ. λ°λμ λ³κ²½ μ νλ‘ μ±λ₯ ν μ€νΈλ₯Ό μ§ννμ¬ λ³λ ¬νλ₯Ό μ¬μ©ν κ°μΉκ° μλμ§ λ°μ Έλ³΄μ.
ArrayList
, HashMap
, HashSet
, ConcurrentHashMap
μ μΈμ€ν΄μ€κ±°λ λ°°μ΄, int λ²μ, long λ²μμΌ λ μ ν©.Stream
μ reduce
λ©μλ μ€ νλ, νΉμ min
, max
, count
, sum
λ±anyMatch
, allMatch
, noneMatch
λ±public class ParallelPrimeCounting {
// μμ κ³μ° μ€νΈλ¦Ό νμ΄νλΌμΈ - λ³λ ¬ν λ²μ
static long pi(long n) {
return LongStream.rangeClosed(2, n)
.parallel()
.mapToObj(BigInteger::valueOf)
.filter(i -> i.isProbablePrime(50))
.count();
}
public static void main(String[] args) {
System.out.println(pi(10_000_000));
}
}