質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

580閲覧

KotlinのIntProgressionにはなぜparallel()が無いの?

mosa

総合スコア218

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2017/10/13 16:20

いつもありがとうございます。
今、teratailの皆さんの助けを借りながらKotlinを勉強しています。

Kotlin の IntProgression は以下のような記述で便利だな、と思うのですが、
Java の parallel() のようなものがなくて不便だなと感じることがあります。

Kotlin

1(1..100 step 2).forEach{ println(it) }

そこで、以下のような拡張関数を考えました。

Kotlin

1fun IntProgression.stream() = IntStream.rangeClosed(first, last).filter{ (it - first) % step == 0 } 2fun IntProgression.parallel() = stream().parallel()

こうすることで、以下のような記述ができます。

Kotlin

1(1..100 step 2).parallel().forEach{ println(it) }

意図している動作はご理解いただけるかと思います。


質問

こんなの元々組み込んであってもよさそうな気もするのですが、ないのは何かマズい点や理由があるからなのでしょうか。
IntProgression は iterator、IntStream は stream というのはわかるのですが、だからダメとはならないと思います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Kotlinのライブラリーインターフェースについて学び始めでしかないので間違ってたらすみません。

だからダメとはならないと思います

想像ですが「標準機能として提供するのは、慎重に考えないとインターフェース破綻の危険があるのではないか」と思います。

KotlinにはIterableとSequenceなどの独自インターフェースがありますね。IntProgressionはKotlin独自のIterableです。IterableがJavaと同様のインターフェースに見えるのになぜわざわざKotlin独自にしているかといえば、Kotlin Iterableがjavaのそれとは異なる機能を備えているからだと思います。例えばJavaではjava.util.stream.Streamでしかリッチなパイプライン機能(変換や集約といったもの)が使えません。一方、KotlinのIterableは拡張関数の力を借りてJavaのIterableよりずっと高機能になっていますね。要するに似てるけど別なインターフェースと言えましょう。

次に並列処理機能について考えると、JavaのStreamにあるparallelはKotlinには見当たりません。コルーチンがまだexperimentalですが、Kotlinはこれなどを用いてJavaとは違う戦略で並列処理機能を設計しようとしているような気がします。

以上から、「KotlinのIterableにJavaのStream固有のparallelを直接記述できるようにしてしまうとKotlinのIterableインターフェースが破たんしかねないのではないか」と想像しました。


余談:

ところで、Kotlin 1.1だと(1..2).asSequence().asStream()のようにするとStreamに変換できるようです。このように明示的に変換する分には混乱はないので一つの方法であるとは思います。

ただ・・・

(1..1000).asSequence().asStream().parallel().forEach(...)

という書き方を考えると、なんだか簡潔とは言い難いですし、それ以上にasStream()が効率よく並列動作できるようなSpliteratorを作ってくれるかが気になります。後者は並列処理のオーバーヘッド(※)にかかわります。その点がどうなっているか不明ですが、Stream#parallelを使うなら、最初からIntStream.rangeを使った方が素直だし安心な気がします。

※: オーバーヘッド
複数スレッド用にパイプラインを分割する際に、一旦上流のパイプラインから一定要素を取り出して配列として蓄積する段取りをふまないと並列動作を始められないことを指します。IntStream.rangeで生成されるIntStreamはこんな処理を必要とせず、S~EのストリームをS~S+PとS+P+1~Eの2つのストリームに即座に分割し並列動作を開始できます。

投稿2017/10/14 02:32

編集2017/10/14 04:17
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mosa

2017/10/14 08:15

ご回答ありがとうございます。 わかりやすく記載していただき、理解できたのですが、 「S~EのストリームをS~S+PとS+P+1~Eの2つのストリームに即座に分割し」のところが全くわからないため、この点、できればより具体的に教えていただくか、参考となるURLなどのご紹介などいただけませんでしょうか。
KSwordOfHaste

2017/10/14 08:33

自分が参照したのはAPIリファレンス(のいささか抽象的な説明)およびIntStreamの内部実装です。 Streamのパイプラインを制御するのはSpliteratorです。これはIteratorに似た動きをして、あるパイプラインが後段のパイプラインへ次に何を渡すかを制御しています。並列化の際にストリームをスレッドの数だけ分割するのはSpliteratorが担う機能なのですが、rangeの結果できるStreamのSpliteratorの実装は単純で、内部に現在値と終了値を覚えてるだけであり「次の値はなに?」と言われたとき「終了値に達してなければ現在値を返し(インクリメントし)、達していれば要素なしとする」みたいになってます。こういう実装ですから、分割位置を決めたとき、2つのSpliteratorに分割するには適当な内部状態に初期化された2つのSpliteratorを生成するだけで済みます。
mosa

2017/10/16 01:40

初めて Stream や StreamSupport, Spliterator の実装を読んでみました。 Java に関しても今まで Stream 関連は使い方の側面しかみていませんでした。 ご回答頂いた内容を踏まえると、並列実行したいからといってIntProgressionである (1..100) を IntStream のシンタックスシュガーのように利用するのはあまり適切ではなさそうですね。 引き続き勉強していきたいと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問