2016-07-01 21 views
3

私はオブジェクト(Property)をArrayList<Property>に入れようとしている小さなアプリケーションに取り組んでいます。基本的に私は何を検索するのMapで動作する検索機能を作っている。条件が不明な文の場合

例:私はそのようにようにするだろう2013年と2015年

の間でリストされていた名前"12 Hello Lane"を持つすべてのプロパティを検索したい:

for (Property p : properties){ 
    if (p.getName().equals("12 Hello Lane") && p.getListingDate().getYear() >=2013 && p.getListingDate().getYear() <= 2015){ 
     //Add to list 
    } 
} 

問題点、私は合格しています比較するプロパティーはMapであり、キーはメソッド名であり、値は希望の値です。言い換えれば、

Key: "getName" 
Value: "12 Hello Lane" 
Key: "getYear" 
Value: 2013-2015 
... 

私の質問は、すべてのプロパティをカバーする単一のif文を使用できるようにする方法ですか?次のようなものがあります。

for (Property p : properties){ 
    if (p.getClass().getMethod(options.getKey()) == options.getValue()){ 
     //Add to list 
    } 
} 

これを正しく表現しているかどうかはわかりませんが、皆さんは私のドリフトを願っています。

編集:私はif a AND b AND c...の効果を達成しようとしています。私は、多くの答えがORに近いものを与えているのを見て、私が明確にすると思っただけです。

答えて

0

あなたは合理的に接近している:

  • あなたのアプローチではなくANDよりも、ORになります。 ANDをご希望の場合は、フラグを作成してループ内に設定し、ループが終了したらチェックしてください
  • 正しく反射していません。ここで

は、あなたがそれを行うことができるはずであるか:

List<Data> allItems = ... 
List<Data> filtered = new ArrayList<>(); 
for (Data d : allItems) { 
    boolean allPass = true; 
    for (Map.Entry<String,String> entry : propertyMap.entrySet()) { 
     Method m = d.getClass().getMethod(entry.getKey()); 
     if (m == null || !entry.getValue().equals(m.invoke(d))){ 
      allPass = false; 
      break; 
     } 
    } 
    if (allPass) { 
     filtered.add(d); 
    } 
} 

Demo.

+0

ありがとうございました。私は朝にこれをチェックする(ちょっと疲れた感じ...)。しかし、これはうまくいくようです... – Riccorbypro

+0

@Riccorbypro問題はありません!デモリンクをクリックすると、何が起こっているのか、そしてこれがあなたが探しているものかどうかを知ることができます。おやすみ! – dasblinkenlight

+0

これはうまくいった!ありがとうございました。 – Riccorbypro

0

時々、これらの状況がどのように存在するのだろうか。 これが一般的な考え方である:あなたの条件から

for (Property p: properties) { 
    boolean shouldAdd = true; 
    for (String method: options.keySet()) { 
     if (p.getClass().getMethod(method).invoke(p) != options.get(key)) { 
      shouldAdd = false; 
      break; 
     } 
    } 
    if (shouldAdd) { 
     //add to list 
    } 
} 
0

あなたは述語ビルダーのいくつかの種類である必要があるように、それが聞こえます。以下に示すこれらの述語を作成するコードを書く必要があります。次にそれらをループして評価を呼び出すことができます。私はあなたが必要とするケースの1つを実装しました。

interface Predicate { 

    boolean evaluate(); 

} 

class StringComparePredicate implements Predicate { 

    final String key; 
    final String value; 

    StringComparePredicate(String key, String value) { 
     this.key = key; 
     this.value = value; 
    }  

    @Override 
    boolean evaluate() { 
     return this.key.equals(this.value); 
    } 
} 

などです。次に、forループを呼び出して各述語について評価を実行することができます。

0

私は最初の理由は単語「プロパティ」のダブルentenderので混乱してしまいました。あなたのような、PropertyAttributeと呼ばれる、別のクラスを作ることができる:

public class PropertyAttribute { 
    private String name; 
    private Object value; 

    public PropertyAttribute(String name, Object value) { 
     this.name = name; 
     this.value = value; 
    } 

    // Applicable getters and setters... 
} 

それではプロパティ以内にあなたがPropertyAttributesのリストを格納することができます

public class Property { 
    public List<PropertyAttribute> attributes = new ArrayList<PropertyAttribute>(); 

    public Property() { 
     // Add to attributes, like: 
     attributes.add(new PropertyAttribute("name", "12 Hello Lane")); 
     attributes.add(new PropertyAttribute("year", "2013 - 2015")); 
    } 
} 

その後、最終的にはあなたのような検索することができます:

for(Property p : properties) { 
    for(PropertyAttribute attr : p.attributes) { 
     if(options.getKey() == attr.getName() && options.getValue() == attr.getValue) { 
      // add to list. 
     } 
    } 
} 
+0

残念なことに、これは私の 'Property'オブジェクトが現在オブジェクトクラス内の変数として属性を持っているので、私のオブジェクトの主要な再構造を必要とします。それぞれの属性にキー/値として設定された属性リストがあることをお勧めしますか? – Riccorbypro

+0

再読みすると、このアプローチは「AND」ではなく「OR」ステートメントになります。私は「AND」を達成しようとしています。 – Riccorbypro

1

魔法をしようとしているすべての答えのうち...ここに私の提案があります。

あなたが実際にしたいことは、各マッチャはこのようになりますMatcher

です...たとえば名前を一致させるためには:

private static Matcher<Property> withName(final String name) { 
    return new BaseMatcher<Property>() { 

     public void describeTo(Description description) { 
      description.appendText("Matches property name to ").appendValue(name); 
     } 

     public boolean matches(Object o) { 
      Property p = (Property) o; 
      return p.name.equals(name); 
     } 
    }; 
} 

その後、あなたはアドレスのマッチャーの数を(持っています、年など)と、リストにすべてのそれらのcriteriasを適用する実際のフィルタ方法:

public List<Property> filter(Matcher<Property>... matchers) { 
    List<Property> valid = new ArrayList<Property>(); //valid ones to return 
    propertyLoop: for (Property property : propertyList) { 
     for (Matcher<Property> matcher : matchers) { 
      if (matcher.matches(property)) { 
       valid.add(property); 
      } else { 
       continue propertyLoop; 
     } 
    } 
    return valid; 
} 

したがって、あなたの最終的なコードは、そのようになります。

List<Property> machingProperties = filter(withName("12 Hello Lane"), withYear(2012, 2015)); 
+0

これは私が必要とするものに対して正しく動作するかどうかはわかりませんが、これもチェックします。 – Riccorbypro