Stream の forEach や、map 、filter 、様々なラムダ式実行の中で、カウンタが必要な時、
しかたなく、AtomicInteger や、グローバルスコープに置いたカウンタインクリメント参照を
よく書いてました。
また、ネット検索してよく紹介されてる例は、実行処理記述で関数型インターフェース定義を書き直す
方法で、以下のような書き方です。
Stream.iterate('A', e->(char)(e+1)).limit(8)
.forEach(new Consumer<Character>(){
int c = 1;
@Override
public void accept(Character t){
System.out.println(c + ":" + t);
c++;
}
});
これだと、t->{ } というラムダ式記述ではなくなって、
関数型インターフェース使用の旨味がなくなってしまいます。
それでは、、、
BiConsumer で書いて、Consumer を返す static メソッドを用意する方法
public static <T> Consumer<T> countCounsumer(BiConsumer<T, Long> biconsumer){
AtomicLong c = new AtomicLong(1);
return t->{
biconsumer.accept(t, c.getAndIncrement());
};
}
以下のように書くことができます。
Stream.iterate('A', e->(char)(e+1)).limit(8)
.forEach(countCounsumer((t, i)->{
System.out.println(i + ":" + t);
}));
static メソッドを都度々、書くのをさけるなら、Consumer を 継承して、、
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
CountCounsumer
public interface CountCounsumer<T> extends Consumer<T>{
public static <T> Consumer<T> of(BiConsumer<T, Long> biconsumer){
AtomicLong c = new AtomicLong(1);
return t->{
biconsumer.accept(t, c.getAndIncrement());
};
}
}
この方が汎用性もあります。
Stream.iterate('A', e->(char)(e+1)).limit(8)
.forEach(CountCounsumer.of((t, i)->{
System.out.println(i + ":" + t);
}));
Stream でカウンタが欲しいのは、forEach だけではないはずで、
例えば、filter ~ Predicate だって、欲しいこともあります。
上と同じように、、static メソッドなら、、
public static <T> Predicate<T> countPredicate(BiPredicate<T, Long> bipredicate){
AtomicLong c = new AtomicLong(1);
return t->{
return bipredicate.test(t, c.getAndIncrement());
};
}
例)
Stream.iterate('A', e->(char)(e+1)).limit(8)
.filter(countPredicate((e, i)->i % 2 == 1))
.forEach(CountCounsumer.of((t, i)->{
System.out.println(i + ":" + t);
}));
Predicate を継承して、、
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
CountPredicate
public interface CountPredicate<T> extends Predicate<T>{
public static <T> Predicate<T> of(BiPredicate<T, Long> bipredicate){
AtomicLong c = new AtomicLong(1);
return t->{
return bipredicate.test(t, c.getAndIncrement());
};
}
}
例)
Stream.iterate('A', e->(char)(e+1)).limit(8)
.filter(CountPredicate.of((e, i)->i % 2 == 1))
.forEach(CountCounsumer.of((t, i)->{
System.out.println(i + ":" + t);
}));