2017-11-05 16 views
3

私はclass A {int sNo; String name;}に有効なコンストラクタを持っています。 ストリームAPIを使用して、名前に基づいて名前を整理し、名前に基づいてソートする必要があります。ストリームとラムダを使用するJavaオブジェクトに対する複数の操作

public class Test1 { 
    public static void main(String[] args) { 



    ArrayList<A> l = new ArrayList(); 
    l.add(new A(1, " 1name ")); 
    l.add(new A(7, " 3name ")); 
    l.add(new A(6, "")); 
    l.add(new A(5, " 2name ")); 
    l.add(new A(4, " 5name ")); 
    l.add(new A(2, "")); 

    List<String> i = l.stream() 
      .filter(s -> !s.name.isEmpty()) 
      .map(s -> s.name.trim()) 
      .sorted() 
      .collect(Collectors.toList()); 
    System.out.println(i); 
} 

}

それだけ

[, 1name, 2name, 3name, 5name] 

ソート順に名前が、私は、オブジェクト全体を必要と返しています。

私はs -> s.name.trim()が提出され、特定の操作を適用するが、オブジェクト全体を格納することができますどのように、

その名前だけを格納した理由であることを知っています。

+0

ご返信いただきありがとうございます。はい、うまく動作していますが、疑問があります。 s - > new A(s.sno、s.name.trim()))はスケーラブルではありません。この例では2つの変数だけを含んでいるので、コンストラクタを呼び出すことはできますが、クラスAでは20 -30の変数は、同じ値を持つコンストラクタを呼び出すのは賢明ではなく、ちょうど私が1を更新するのは賢明ではありません。 –

答えて

1

あなたがmap機能を使用するときは、文字列の中に、すべてのオブジェクトを変換し、その代わりに、マップの、オブジェクト内の文字列を変換するごとに使用しますが、文字列のリストを返すされていません。

class A { 
int sNo; 
String name; 

public int getName(){ return name} 



public void setName(String name){ this.name = name;} 

    } 

i.forEach(s -> s.setName(s.getName().trim())); 

List<A> i = l.stream() 
     .filter(s -> !s.name.isEmpty())  
     .sorted(Comparator.comparing(a -> a.name)) 
     .collect(Collectors.toList()); 
+0

'forEach(s - > s.name.trim())'は何を信じていますか?つまり、CPUを使い切る以外のことですか? – Andreas

+0

@Andreasあなたは正しいです、オブジェクトの状態を更新するための値を設定するのを忘れました –

+0

@アンドレアス私は答えを今更新しました。ありがとう、 –

1

名前はソートされた順番でのみ返されています[...]しかし、私はオブジェクト全体が必要です。

.map(s -> s.name.trim())ステップはStringの流れの中にAのあなたのストリームに変換します。そのため、オブジェクト全体ではなく文字列が残っています。

オブジェクトのソートされたリストが必要な場合は、結果はではなくList<A>になります。

オブジェクトのリストをフィールドでソートするには、Comparatorsortedに渡すことができます。

List<A> result = l.stream() 
    .filter(s -> !s.name.isEmpty()) 
    .map(s -> new A(s.sNo, s.name.trim())) 
    .sorted(Comparator.comparing(a -> a.name)) 
    .collect(Collectors.toList()); 

あなたは、トリミングされた名前でnew Aを作成したい が、元のオブジェクトを(私は真剣に疑うが)変更したくない場合は、 あなたはpeekmapステップを交換し、変更することができますオブジェクトは:

.peek(s -> s.name = s.name.trim()) 

しかし、@Mustafaが指摘したように、peekはデバッグのためだけに意図されていることに注意してください。実際、基礎となるオブジェクトを変更したい場合は、フィルタリングとソートとは別のステップでは、 という論理的に無関係なステップです(データクリーニングのように見えます)。 そのステップはforEachを使用して実装できます。

あなたが実際に名前(ヒントのおかげ@Andreas)をトリミングする必要がない場合は、 のみ仕分けの目的のために、 あなたは、完全にmapステップをドロップ し、このようなsortedステップを書くことができます:

.sorted(Comparator.comparing(a -> a.name.trim())) 
+0

'sorted(Comparator.comparing(a - > a.name.trim()))'を実行するだけです。確かに、パフォーマンスは良くありませんが、動作し、 'map()'の必要性がなくなります。 – Andreas

+0

@アンドレアス私は、OPが実際にトリミングされた値を並べ替えるだけでなく、文字列をトリミングしたいという印象を受けました。しかし、あなたのアイデアはもっとありそうです、ありがとう、私は私の答えを更新しました。 – janos

+0

新しいオブジェクトを作成する方が良いです。それ以外の場合は、 'peek'よりも' forEach'を使うことをお勧めします。 [documentation](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#peek-java.util.function.Consumer-)によると、 'peek'デバッグのためのものです。 – Mustafa

2

特に楽しいのではなく、特に素晴らしい、または推奨されているからではありません。(javac意志)

List<A> i = l.stream() 
      .filter(s -> !s.name.isEmpty()) 
      .map(s -> new Object() {A a = s; String name = s.name.trim();}) 
      .sorted(Comparator.comparing(o -> o.name)) 
      .map(o -> o.a) 
      .collect(Collectors.toList()); 

必ずしもすべてのコンパイラはこのことについて幸せになりますが、それは有効なJavaコードです:一つは、匿名のオブジェクトでも、それを達成できました。

関連する問題