2017-07-01 5 views
9

私は、Java DateTimeFormatterのパターンの組み合わせを次のようにして、"E".."EEEE""M".."MMMM"のパターンの組み合わせを持っています。サブ文字列のストリームを結合する

この場合、Javaストリームを使用するための慣用的な方法がありますか?

import java.time.LocalDateTime; 
import java.time.format.DateTimeFormatter; 
import java.util.stream.IntStream; 
import java.util.stream.Stream; 

public class DateTimeFormattingStackOverflow { 
    static LocalDateTime dateTime = LocalDateTime.now(); 

    static Stream<String> substrings(String str) { 
     return IntStream.range(1, str.length() + 1) 
       .mapToObj(i -> str.substring(0, i)); 
    } 

    static void printDateTime(String pattern) { 
     DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern); 
     System.out.println(pattern + ", " + dtf.format(dateTime)); 
    } 

    public static void main(String[] args) { 
     Stream<String> patterns = substrings("EEEE") 
       .flatMap(e -> substrings("MMMM").map(m -> e + " " + m)) 
       .map(em -> em + " d"); 

     patterns.forEach(DateTimeFormattingStackOverflow::printDateTime); 
    } 
} 

私はあなたが、文字の繰り返しの実行を生成する方法に変更となる出力

E M d, Sat 7 1 
E MM d, Sat 07 1 
E MMM d, Sat Jul 1 
E MMMM d, Sat July 1 
EE M d, Sat 7 1 
EE MM d, Sat 07 1 
EE MMM d, Sat Jul 1 
EE MMMM d, Sat July 1 
... 
+0

ストリームと一緒にする必要があるのですか、それとも別の慣用的な方法かもしれませんか? –

+0

私は特に 'ストリーム方式'でこれを行うことに関心を持っていましたが、このコードの非ストリーム版が等しく/もっと慣用的なJavaであることは間違いありません。 –

答えて

0

:むしろ手動で最長の文字列を構築し、そのプレフィックスを反復処理よりも、私はCollection.nCopiesと実行を構築します、次のように:

static Stream<String> repeatedRuns(String c, int start, int end) { 
    return IntStream 
     .rangeClosed(start, end) 
     .mapToObj(len -> 
      Collections.nCopies(len, c).stream().collect(Collectors.joining("")) 
     ); 
} 

その後、repeatedRuns("E", 1, 4)substrings("EEEE")を置き換えます。

Demo.

0

ことがより慣用的である場合、私は知りませんが、私は、単一のメソッドにそれを絞るだろう

public static Stream<String> combinations(String first, String second, String d, LocalDateTime dateTime) { 

     Stream<String> s = IntStream.range(0, first.length()) 
       .mapToObj(i -> first.substring(0, i + 1)) 
       .flatMap(x -> IntStream.range(0, second.length()) 
         .mapToObj(i -> second.substring(0, i + 1)) 
         .map(m -> String.join(" ", x, m)) 
         .map(res -> res + " d") 
         .peek(System.out::print) 
         .map(DateTimeFormatter::ofPattern) 
         .map(dtf -> dtf.format(dateTime))); 
     return s; 
    } 

    combinations("EEEE", "MMMM", " d", LocalDateTime.now()).forEach(x -> System.out.println(", " + x)); 
+0

'String.join(" "、x、m)'は単に 'x +" "+ m"よりも優れているとは思っていませんが、好きなスタイルであれば、 '.map(res - > res +" d ")'を実行します。特に、ある操作でそれを行うことができるように、 'String.join(" "、x、m、" d ")'または 'x +" "+ m +" d "' ... – Holger

+0

@君は – Eugene

1

あなたが使用している(それはちょうど私が...することができます) IntStreamドライブ文字列。それはそれを行うための一つの方法だし、ここでは他の二つの方法があります。

static Stream<String> substrings2(String str) { 
    return Stream.iterate(str, s -> s.substring(1)).limit(str.length()); 
} 

これはに与えられた関数を適用します。

static Stream<String> substrings(String str) { 
    return str.length() == 1 ? Stream.of(str) : 
      Stream.concat(Stream.of(str), substrings(str.substring(1))); 
} 

は、次のように他の方法は次のようになりながら、これは、再帰的にStreamを作成し、前回の結果。無限のストリームを作成するので、limitを使用する必要があります。

私は少しあなたが1つのmap操作を避けるように、あなたのmain方法を変更しました:

substrings("EEEE") 
    .flatMap(e -> substrings("MMMM").map(m -> e + " " + m + " d")) 
    .forEach(DateTimeFormattingStackOverflow::printDateTime); 

を上記の方法は、多かれ少なかれ慣用あなたの方法に比べている場合、私は本当に知らないが、あなたは私に言わせれば、この作業を行うには、最も慣用的な方法は、ネストされたループである:

String e = "EEEE"; 
String m = "MMMM"; 

for (int i = 0; i < e.length(); i++) 
    for (int j = 0; j < m.length(); j++) 
     printDateTime(e.substring(i) + " " + m.substring(j) + " d"); 

、次のようにこれは、Java 8に変換される可能性があります:

IntStream.range(0, e.length()).boxed() 
    .flatMap(i -> IntStream.range(0, m.length()) 
     .mapToObj(j -> e.substring(i) + " " + m.substring(j) + " d")) 
    .forEach(DateTimeFormattingStackOverflow::printDateTime); 
0

サブストリングをまったくストリームしません。これらは、4回4つの組み合わせであるという事実が安いビット演算の計算対象とします

Stream<String> patterns = IntStream.range(0, 16).map(i -> 15-i) 
    .mapToObj(i -> "EEEE".substring(i>>2)+" "+"MMMM".substring(i&3)+" d"); 

が、原則として、いかなる:それは16個の組み合わせを表現する何か経由でストリーミングすると、一回の操作でフォーマット文字列を構築するのに十分ですN×メートル組み合わせは、から0 N×メートルからのストリーミングおよび(substring操作を行うような)要素を選択するためのi/ni%nを使用することにより可能です。前の.map(i -> 15-i)の手順は、元のコードと一致するように順序を逆順にします。順序が重要でない場合は省略することができます。

関連する問題