はじめに
こちらの記事にも書いている、IntStream.range()とIntStream.rangeClosed()は、指定した範囲の連続する値を得る際に非常に便利です。
しかし、これらのメソッドで得られたIntStreamは、sortedメソッドだけでは逆順にできません。
例えば以下のコードの場合、sortedメソッドの引数にComparator.reverseOrder()をとることが出来ないため、コンパイルエラーとなってしまいます。
※IntStreamクラスのsortedメソッドは、引数を持たないメソッドとして定義されています。
static void reverse() {
IntStream.rangeClosed(1, 10) // IntStreamの生成
.sorted(Comparator.reverseOrder()) // 中間操作
.forEach(num -> System.out.println(num)); // 終端処理
}
解決策1:boxedメソッドの利用
中間処理としてboxedメソッドを入れて、IntStreamをStream<Integer>に変換することで、sortedメソッドだけで簡単に逆順にすることができました。
※Streamクラスのsortedメソッドは、Comparatorを引数にとることができます。
static void reverse() {
IntStream.rangeClosed(1, 10) // IntStreamの生成
.boxed() // ★追加した中間操作(IntStream->Stream<Integer>)
.sorted(Comparator.reverseOrder()) // 中間操作
.forEach(num -> System.out.println(num)); // 終端処理
}
解決策2:IntStreamの使用を諦める
IntStreamを使わずにStream(Stream<Integer>)を使えば、この問題を回避することができます。
その代わり、IntStream.range()とやIntStream.rangeClosed()などは使えなくなってしまいます...
static void reverse2() {
Integer[] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Stream<Integer> stream = Arrays.stream(values);
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Arrays.stream(values) // streamの生成
.sorted(Comparator.reverseOrder()) // 中間操作
.forEach(num -> System.out.println(num)); // 終端処理
}
/**
* @k73i55no5さんによる改善版。listを介さずに直接配列からstreamに変換している。
*/
static void reverse3() {
Integer[] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Arrays.stream(values) // streamの生成
.map(num -> num * 2) // 中間操作
.sorted(Comparator.reverseOrder()) // 中間操作
.forEach(num -> System.out.println(num)); // 終端処理
}
解決策3:符号を変換してからソートする
@swordoneさんからコメントで教えて頂いた方法で、「プラスマイナスの符号を変換して並べ替えた後、再び符号を元に戻す」というものです。
こちらでは未確認ですが、この方法を使うには幾つかの制約があるようです。
コメントでは「ネタ」と言われていますが、全く想定していない方向からボールが飛んできたように感じるほど驚きました。
static void reverse4() {
IntStream.rangeClosed(1, 10) // streamの生成
.map(i -> -i) // 中間操作(正の数->負の数)
.sorted() // 中間操作
.map(i -> -i) // 中間操作(負の数->正の数)
.forEach(num -> System.out.println(num)); // 終端処理
}
まとめ
- 「IntStreamをStream<Integer>に変換する」という方法で解決できるとは思いませんでした。
- そもそも、IntStreamとStream<Integer>の違いを全く理解していなかったです...
- 解決策2は単なる逃げですが、絶対にIntStreamを使わなければダメということでなければ、これで良いのかもしれません。
- Java8のStream APIは苦手(というより使う機会がない)なので、少しでも触れる機会を増やしていきたいです。
- @LouiS0616さんのコメント(※mapメソッドを使う方法)については、もう少し勉強してから追記したいと思います。