2012-03-20 10 views
1

私はpojoのList<Pojo> pojoListのリストを持っています。 pojo.getColour();はEnumインスタンスを返します。メンバー変数またはマッピング関数に基づくサブリストを返します。

そして、私はこれをしたい:

List<Pojo> newlist = new ArrayList<Pojo>(); 
for(Pojo pojo:pojoList){ 
    if(pojo.getColour() == Colour.Red){ 
    newList.add(pojo); 
    } 
} 
私はそれが一般的なようにする方法が自分で他の種類のリストに同様の機能を使用してそうではなく、多くのコードを繰り返す自分を見ることができました

および/または機能性?私は別のルールに基づいて異なるタイプのサブリストを作成することができましたか?

答えて

6

まず第一に、私はあなただけのマッチング要素を含む新しいArrayListをしたい場合、あなたはあなたの例でそれをやった方法がうまくあることに注意してください。 Javaにラムダ式があるまでは、それよりも簡単で見栄えが良くなりません。

これをとタグ付けしたので、ここであなたはになる可能性があります。 Guavaでこれを行います。基本的には、述語の構成(== Color.Red)と関数(pojo.getColour())の元のリストをフィルタリングしています。あなたは(このような)PojoCOLOURという静的最終Function<Pojo, Colour>を持っていたのであれば:

public static final Function<Pojo, Colour> COLOUR = 
    new Function<Pojo, Colour>() { 
     @Override public Colour apply(Pojo input) { 
     return input.getColour(); 
     } 
    }; 

あなたは、このようにその組み合わせを作成することができます。

Predicate<Pojo> isRedPojo = Predicates.compose(
    Predicates.equalTo(Colour.Red), Pojo.COLOUR); 

をあなたはその後、元のリストのフィルタされたビューを作成することができます:

Iterable<Pojo> redPojos = Iterables.filter(pojoList, isRedPojo); 

そして、あなたがしたい場合は、ArrayListにそのフィルタされたビューをコピーすることができます:

List<Pojo> copy = Lists.newArrayList(redPojos); 
+2

apons commons-collectionsにもこのための良いユーティリティがあります。コレクション filtered = CollectionUtils.filter(pojoCollection、新しい述語(){...}); – Matt

+2

@Matt:私はcommons-collectionsフィルタメソッド_removes_は、私が本当に好きではない元のコレクションと一致しない要素だと思います。 Guavaには、それを行うために、より明示的に 'Iterables.removeIf(Iterable、Predicate) 'という名前のメソッドがあります。 – ColinD

+0

'Function'の外観を指定できますか? – hakunami

1

あなたはあなたのタイプをチェックするための共通のインターフェースを実装するために必要があるだろう:

public interface Candidate { 
    public boolean isAddable(); 
} 

ループは、この

List<Candidate> newlist = new ArrayList<Candidate>(); 
for(Candidate pojo:pojoList){ 
if(pojo.isAddable()){ 
    newList.add(pojo); 
} 
} 

のようになりますとPojoクラスが実装しなければなりませんインタフェース:

public class Pojo implments Candidate { 

    // ... 

    @Override 
    public boolean isAddable() { 
    return isRed(); 
    } 
} 
+0

要素を選択するための厳密に1つの基準(isAddable()実装)を定義するために 'Candidate'実装を必要とすることはあまりにも制限的だと思います。述語/マッチャベースのアプローチは、要素をフィルタリングするための任意の数の異なる方法を可能にする。 – ColinD

1

一般的なフィルタインターフェイスを作成

public interface Filter<T>{ 
    public boolean match(T item); 
} 

フィルタ

public <T> List<T> getFilteredList(List<T> oldList, List<T> filter){ 
    List<T> newlist = new ArrayList<T>(); 

    for(T item:oldList){ 
     if(filter.match(item)){ 
     newlist.add(item); 
     } 
    } 

    return newlist; 
} 

を用いる方法を作るには、あなたがそれを使用する頻度/どのように多くの異なるフィルタ(赤のみ、のみ、緑などに応じて、一緒に

List<Pojo> myList = .. 

List<Pojo> redList = getFilteredList(myList,new Filter<Pojo>(){ 
     public boolean match(Pojo item){ return item.isRed()}; 
}); 

List<Pojo> blueList = getFilteredList(myList,new Filter<Pojo>(){ 
     public boolean match(Pojo item){ return item.COLOR== Color.BLUE}; 
}); 
1

それをすべて置きます。)あなたが使用しているのであれば、Filterインターフェースを作成することは意味があります。isRedをチェックするだけの場合は、コードが多すぎるかもしれません。単純な静的メソッドを使う方が良いでしょう。

このデザインの良い点は、フィルタリングするオブジェクト(この例では下の文字列の例を参照)で使用できることです。

public static void main(String[] args) { 
    List<Pojo> originalList = Arrays.asList(new Pojo(true), new Pojo(false), new Pojo(false)); 
    List<Pojo> filteredList = Utils.getFilteredList(originalList, new Filter<Pojo>() { 
     @Override 
     public boolean match(Pojo candidate) { 
      return candidate.isRed(); 
     } 
    }); 
    System.out.println(originalList.size()); //3 
    System.out.println(filteredList.size()); //1 

    //Now with strings 
    List<String> originalStringList = Arrays.asList("abc", "abd", "def"); 
    List<String> filteredStringList = Utils.getFilteredList(originalStringList, new Filter<String>() { 
     @Override 
     public boolean match(String candidate) { 
      return candidate.contains("a"); 
     } 
    }); 
    System.out.println(originalStringList.size()); //3 
    System.out.println(filteredStringList.size()); //2 
} 

public static class Utils { 
    public static <T> List<T> getFilteredList(List<T> list, Filter<T> filter) { 
     List<T> selected = new ArrayList<>(); 
     for (T t : list) { 
      if (filter.match(t)) { 
       selected.add(t); 
      } 
     } 
     return selected; 
    } 
} 

public static class Pojo { 
    private boolean isRed; 

    public Pojo(boolean isRed) { 
     this.isRed = isRed; 
    } 

    public boolean isRed() { 
     return isRed; 
    } 
} 

public interface Filter<T> { 

    /** 
    * When passed a candidate object, match returns true if it matches the filter conditions, 
    * or false if it does not. 
    * @param candidate the item checked against the filter 
    * @return true if the item matches the filter criteria 
    */ 
    boolean match(T candidate); 
} 
関連する問題