形式の文字列が1つあります。
_row1col1 row1col2
row2col1 row2col2
row3col1 row3col2
_
等々...
各アイテムを抽出して、次のようなプロパティを持つオブジェクトの配列を構築したいと思います。
_new MyObject(row1col1, row1col2);
_
Java 8とStreamsは初めてです。ループなしでこれを実現する方法を知りたいです。
通常、行をStringの配列に累積するためにString.split('\n')
を使用します
そして、各行についてスペースセパレーターで再度分割し、処理する行がなくなるまで、2つの要素の配列(_row1col1 row1col2
_)でオブジェクトを構築するループ。
このような:
_String sausage = "row1col1 row1col2\nrow2col1 row2col2\nrow3col1 row3col2";
String[] rows = sausage.split("\n");
for (String row : rows) {
String[] objectData = u.split("\\s+");
MyObject myObject = new MyObject(objectData[0], objectData[1]);
myObjectList.add(myObject);
}
_
誰かが私にストリームで同じことを達成する方法を説明できますか、そしてそれを可能にする背後にあるメカニズムは何ですか?
すべての例から、ストリームはフィルタリング、収集、または一般に一連の要素がいくつかの基準を適用してマイナーセットを取得することに焦点を当てているので、これは要素数を増やすときにも有効な考え方です。
簡単な方法は、行区切り文字を使用してPattern
を作成し、入力String
をStream
として分割することです。次に、各行がスペースで分割され(2つの部分のみを保持)、MyObject
にマップされます。最後に、結果を使用して配列が作成されます。
_public static void main(String[] args) {
String str = "row1col1 row2col2\r\nrow2col1 row2col2\r\nrow3col1 row3col2";
MyObject[] array =
Pattern.compile(System.lineSeparator(), Pattern.LITERAL)
.splitAsStream(str)
.map(s -> s.split("\\s+", 2))
.map(a -> new MyObject(a[0], a[1]))
.toArray(MyObject[]::new);
System.out.println(Arrays.toString(array));
}
_
入力splitAsStream
が長い場合、 String
を使用すると、Stream.of(...)
よりも有利になります。
コードでは、String
の行セパレーターがOSのデフォルトの行セパレーター(System.lineSeparator()
)であると想定しましたが、そうでない場合は変更できます。
代わりに、ファイルから読み取る場合は、Files.lines()
を使用して、ファイル内のすべての行のStream
を取得できます。
_MyObject[] array = Files.lines(path)
.map(s -> s.split("\\s+", 2))
.map(a -> new MyObject(a[0], a[1]))
.toArray(MyObject[]::new);
System.out.println(Arrays.toString(array));
_
単一のStream
インスタンスを表すString
のMyObject
を生成し、それぞれをMyObject
インスタンスに変換することができます(最初に再度分割して、次にMyObject
インスタンスを作成します):
List<MyObject> list =
Stream.of(inputString.split("\n"))
.map (s -> s.split(" "))
.filter (arr -> arr.length == 2) // this validation may not be necessary
// if you are sure each line contains 2 tokens
.map (arr -> new MyObject(arr[0],arr[1]))
.collect(Collectors.toList());