0

特定のルールに基づいてリストからいくつかのアイテムを除外する最良の方法を見つけようとしています。たとえば、

public class Person{
    String name;
    String sex;
    String dob;
    String contactNo;
    Person(String name, String sex, String dob, String contactNo) {
        this.name = name;
        this.sex = sex;
        this.dob = dob;
        this.contactNo = contactNo;
    }
}

List<Person> persons = Arrays.asList(new Person("Bob", "male", "19800101", "12345"),                
        new Person("John", "male", "19810101", "12345"),
        new Person("Tom", "male", "19820101", "12345"),
        new Person("Helen", "female", "19800101", "12345"),
        new Person("Jack", "male", "19830101", "12345"),
        new Person("Suan", "female", "19850101", "12345"));

同じ dob と contactNo を持つ男性と女性のペアを削除したい (上記の例では Bob と Helen を削除します)。ネストされたループを使用して、これを以下のように実装しました。これを達成するためのより良い方法はありますか? これを行うために述語を実装できますか?

public void filterPersons() {       
    List<Person> filtered = new ArrayList<Person>();

    for (Person p: persons) {
        boolean pairFound = false;
        for (Person t: persons) {
            if ((p.sex.equals("male") && t.sex.equals("female")) || (p.sex.equals("female") && t.sex.equals("male"))) {
                if (p.dob.equals(t.dob) && p.contactNo.equals(t.contactNo)) {                       
                    pairFound = true;
                    break;
                }
            }
        }
        if (!pairFound) {filtered.add(p);}          
    }

    System.out.println("filtered size is: " + filtered.size());
    for (Person p: filtered) {
        System.out.println(p.name);
    }
}

どうもありがとう。

上記の方法を以下のように書き直しました。

public void testFilter() {      
    Predicate<Person> isPairFound = new Predicate<Person>() {
        @Override public boolean apply(Person p) {              
            boolean pairFound = false;
            for (Person t: persons) {
                if ((p.sex.equals("male") && t.sex.equals("female")) || 
                        (p.sex.equals("female") && t.sex.equals("male"))) {
                    if (p.dob.equals(t.dob) && p.contactNo.equals(t.contactNo)) {                       
                        pairFound = true;
                        break;
                    }
                }
            }
            return pairFound;
        }
    };

    Iterable<Person> filtered = Iterables.filter(persons, isPairFound);     
    for (Person p: filtered) {
        System.out.println(p.name);
    }
}
4

3 に答える 3

1

ネストされた for ループが特に醜いとは思いません。事実上任意の基準に基づいてリスト内のアイテム間の一致を探しているため、すべてのエントリを他のすべてのエントリと比較する必要があります。

検討できる改善の 1 つは、反復コードを比較ロジックから分離することです。これは、述語で向かっていた場所です。これを行うには、1 つではなく 2 つのオブジェクトを取る Predicate が必要です。

public interface PredicateComparator<T> {
    boolean compare(T o1, T o2);
}

コードは次のようになります

public void filterPersons() {

    PredicateComparator<Person> predicate = new PredicateComparator<Person>() {
        public boolean compare(Person o1, Person o2) {
            // comparison logic in here
        }

    };

    List<Person> filtered = new ArrayList<Person>();
    for (Person p : persons) {
        for (Person t : persons) {
            if (predicate.compare(p, t)) {
                filtered.add(p);
            }
        }
    }

    System.out.println("filtered size is: " + filtered.size());
    for (Person p: filtered) {
        System.out.println(p.name);
    }
} 
于 2013-11-14T14:30:15.740 に答える
0

2 人の身元を確認する方法は 1 つだけですか? もしそうなら、'equals' と 'hashcode' をオーバーライドしてこれをカプセル化するのが最善でしょう。

これを行った後、次のいずれかのアプローチを取ることができます。

  1. Person インスタンスのコレクションを作成していて、同じ人物を複数回追加するときにコレクション内の単一のインスタンスのみが保持されるようにしたい場合は、Set インターフェイスを基になるコレクション (およびおそらく HashSet 実装) として使用します。equals と hashcode が適切に配置されていれば、セットは重複を許しません。

  2. コレクションが与えられた場合(つまり、その作成を制御できないため、上記のアプローチを使用して重複なしで構築されていることを検証することはできません) で、重複したインスタンスを除外したい場合は、単純にそれをコンストラクターにフィードできます。次のようなハッシュセット:

    Collection<Integer> containsRepeatingNumbers = Arrays.asList(1,2,3,4,3,3,3,3);
    Set<Integer> alldistincts = new HashSet<>(containsRepeatingNumbers);
    System.out.println(alldistincts);   //[1, 2, 3, 4]
    

ところで、将来アイデンティティの複数の基準が予想される場合は、ここで提案されている戦略を使用できます

于 2013-11-14T13:56:34.410 に答える