u-ryo's blog

various information for coding...

Category: Stream

List to Map in Java

| Comments

JavaでListMapにしたかったんですね。 【Java入門】List⇔Map変換でJava8のStreamを使う方法を見ました。 ここは、いいこと書いてあるんですけど能書きが長い、Java8以前の話は不要(at least for me)、広告が多い感じがする、のが...

基本は単純にCollectors.toMap(s->key, s->value)でいけますと。 但し、duplicated keyがあった場合即Exceptionに。

1
2
3
4
5
6
7
8
9
10
11
12
13
jshell> Stream.of("A quick brown fox jumps over the lazy dog.".split(" ")).collect(Collectors.toMap(s->s.length(),s->s)
   ...> )
|  java.lang.IllegalStateException thrown: Duplicate key 5 (attempted merging values quick and brown)
|        at Collectors.duplicateKeyException (Collectors.java:131)
|        at Collectors.lambda$uniqKeysMapAccumulator$1 (Collectors.java:178)
|        at ReduceOps$3ReducingSink.accept (ReduceOps.java:169)
|        at Spliterators$ArraySpliterator.forEachRemaining (Spliterators.java:948)
|        at AbstractPipeline.copyInto (AbstractPipeline.java:484)
|        at AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:474)
|        at ReduceOps$ReduceOp.evaluateSequential (ReduceOps.java:913)
|        at AbstractPipeline.evaluate (AbstractPipeline.java:234)
|        at ReferencePipeline.collect (ReferencePipeline.java:511)
|        at (#9:1)

なので、Collectors.toMap(s->key, s->value, (s1,s2)->do)のようにduplicated keyがあった場合の処理もlambdaとして第三引数に書けます。 後勝ちの例↓

1
2
jshell> Stream.of("A quick brown fox jumps over the lazy dog.".split(" ")).collect(Collectors.toMap(s->s.length(),s->s,(s1,s2)->s2))
$11 ==> {1=A, 3=the, 4=dog., 5=jumps}

SQLっぽくCollectors.groupingBy(s->key)を使うと、重複valuesはListに込めてくれるので楽です。

1
2
jshell> Stream.of("A quick brown fox jumps over the lazy dog.".split(" ")).collect(Collectors.groupingBy(s->s.length()))
$12 ==> {1=[A], 3=[fox, the], 4=[over, lazy, dog.], 5=[quick, brown, jumps]}

Flatten Lists in a List in Java

| Comments

Javaでlistの中にlistが複数あるものを、 一つのflatなlistにしたい時、どうするのかなー、と。 Java 8 で ruby の flattenに書いてありました。

1
2
jshell> List.of(List.of("a","b","c"),List.of("d","e"),List.of("f","g")).stream().flatMap(Collection::stream).collect(Collectors.toList())
$7 ==> [a, b, c, d, e, f, g]

flatMap(Collection::stream)がキモですね。 こんなの思い付かないですよ。

Negate Method Reference

| Comments

Javaのstreamで、filter(s -> !s.isEmpty())を method referenceに出来ないかなー、と思ったんですが、 java.util.function.Predicateを使って、

  1. Java11だとfilter(Predicate.not(String::isEmpty))
  2. 現状ではfilter(((Predicate<String>) String::isEmpty).negate())と長くなる
  3. 下記のように自分で定義してfilter(not(String::isEmpty))
1
2
3
public static <T> Predicate<T> not(Predicate<T> t) {
    return t.negate();
}

cf. stack overflow: How to negate a method reference predicate

現状では長くなるので、やめました。

Rx as Stream API

| Comments

周知のように、Androidではlambdaは書けるようになりましたが Stream APIのようにCollectionsを扱えません。 折角Java8で覚えたのに。 ですが、RxJavaを使うとほぼStream APIのように書けるんですねーへーーー。 非同期や並列処理にも役立つRxJavaの使い方 おかげでloopを回さず一文になったので、 ifの条件節に直接書けるようになりました。 Optionalも出来るんですね。 書いてありますが、キモはtoBlocking().single()でしょうか。