ふたつの Iterator を LINQ で

を拝見しました。

コメントで「Zip じゃん」というのがあり、「確かに!」と思ったのでやってみました。

C# の場合

// using using System.Linq;

var arr1 = new int[] { 1,2,3,4,5 };
var arr2 = new string[] { "hoge", "fuga", "piyo" };

arr1.Zip(arr2, (x, y) =>  new {x, y})
    .ToList()
    .ForEach(Console.WriteLine);

結果

{ x = 1, y = hoge }
{ x = 2, y = fuga }
{ x = 3, y = piyo }

うむ、シンプル。要素数が違ってても少ない方に合わせてくれます。

Java の場合

reactive4java というライブラリがありまして、これは Java で Reactive Extensions を実現するライブラリなのですが、LINQ的な機能が Interactive というクラスで提供されています。

これを使うと Zip ができます。

//import hu.akarnokd.reactive4java.base.Func2;
//import hu.akarnokd.reactive4java.interactive.Interactive;

Iterable<Integer> array1 = Arrays.asList(1,2,3,4,5);
Iterable<String> array2 = Arrays.asList("hoge", "fuga", "piyo");

Iterator<Pair<Integer, String>> zippedIter = 
		Interactive.zip(array1, array2, 
				new Func2<Integer, String, Pair<Integer, String>>() {
	@Override
	public Pair<Integer, String> invoke(Integer x, String y) {
		return new Pair<Integer, String>(x, y);
	}
}).iterator();

while (zippedIter.hasNext()) {
	Pair<Integer, String> p = zippedIter.next();
	Log.d("StartupActivity", String.format("x=%d, y=%s", p.first, p.second));
}

ああ、Android で試したので Pair とか使ってしまった。
普通の Java の場合は自作の Tuple などに置き換えを。

結果

x=1, y=hoge 
x=2, y=fuga 
x=3, y=piyo 

C# より冗長ですけど、いい感じで利用できるのではと思います。

reactive4java が Java8 のラムダ式に対応してくれると、上のコードはもっと簡潔に書けます。

Reactive4Java8 には、対応してる感じが見られますが、Top ページ によると、どうやら、「reactive4java の開発は終了し、RxJava の開発に参加するつもりだ」みたいなことが書いてあります。

また、RxJava でなく reactive4java を使う利点として、Interactive 機能群の存在を挙げています。
単純に LINQ 的な機能を Java で使いたいならば、 reactive4java はまだまだ役に立つと思います。

最後に、もしあなたが Android 開発をしていて、Java の冗長さに嫌気がさしているなら、Xamarin へどうぞ

amay077

Microsoft MVP(Xamarin). フルリモートワーカー. Geospatial Mobile app developer. Love C#.

amay077 amay077