web-dev-qa-db-ja.com

Java文字列配列上の8ストリーム

形式の文字列が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);
}
_

誰かが私にストリームで同じことを達成する方法を説明できますか、そしてそれを可能にする背後にあるメカニズムは何ですか?

すべての例から、ストリームはフィルタリング、収集、または一般に一連の要素がいくつかの基準を適用してマイナーセットを取得することに焦点を当てているので、これは要素数を増やすときにも有効な考え方です。

11
Lucian Enache

簡単な方法は、行区切り文字を使用してPatternを作成し、入力StringStreamとして分割することです。次に、各行がスペースで分割され(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));
_
11
Tunaki

単一のStreamインスタンスを表すStringMyObjectを生成し、それぞれを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());
6
Eran