コレクションで重複を見つける

コレクション内の重複したオブジェクトを見つけてマークする最良の方法は何ですか?リストの人がいるとし、重複戦略は名と姓の完全一致に基づいているとしましょう。

  1. すべての重複を特定する
  2. 重複している人物が重複していることを示すマークを付けてください
  3. 各重複する人物について、それが重複しているオブジェクトを特定する

グアバでこれを行う簡単な方法はありますか?

5
あなたが「重複しているオブジェクトを特定する」という意味を明確にすることはできますか?最初のアイテムが「本当の」アイテムであり、後続のアイテムが重複していると思われますか?
追加された 著者 Christian Gruber,

4 答え

これを行うにはGuavaは必要ありません。

List people = ...
Map peopleByName = new HashMap<>();
for (Person person : people) {
 //Name is a simple value class with equality based on its fields
  Name name = new Name(person.getFirstName(), person.getLastName());
  Person firstPersonWithName = peopleByName.get(name);
  if (firstPersonWithName == null) {
    peopleByName.put(name, person);
  } else {
   //or whatever you do to mark a duplicate
    person.setDuplicateOf(firstPersonWithName);
  }
}

つまり、 Map の代わりにGuava Table を使用し、 Name を作成する必要がなくなります。キーと姓の列キーとして、例えば言う。

もう一つの選択肢は、 Multimaps.index を使用して、リスト内のすべての人物を名前で索引付けすることです。その後、特定の名前にマッピングされた人のリストごとに、最初の人物がリストの名前を持つ最初の人物になり、他の人物は重複したものになります。

5
追加された

Guavaのツリーマルチマップ]を使用して、 a>。

Create a new one TreeMultimap initializing it with a comparator for comparing you persons as you like:

TreeMultimap.create(Comparator, Ordering.arbitrary())

ユニットテストです:

package org.test.guava;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import org.junit.Test;

import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
import com.google.common.collect.TreeMultimap;

public class GuavaTest {

    private static class Person {
        private String name;

        public Person(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return "Person [name=" + name + "]";
        }

    }

    @Test
    public void test() throws Exception {
        List persons = Arrays.asList(new Person("person1"), new Person("person2"), new Person("person1"));
        Comparator comparator = new Comparator() {
            public int compare(Person o1, Person o2) {
                return o1.getName().compareTo(o2.getName());
            }
        };

        Multimap groups = TreeMultimap.create(comparator, Ordering.arbitrary());
        for(Person person : persons) {
            groups.put(person, person);
        }

        System.out.println(groups.asMap());
    }

}
2
追加された
私は質問から3番の要件をどのように満たすことができますか?
追加された 著者 Aravind R. Yarram,
ソートされたマルチマップを使用する必要はなく、別のキーの等価性を選択する方法として使用しているので、意図が明確ではありません。名前自体をキーとして使用する方が望ましいです。次に、 Multimaps.index を使用できます。
追加された 著者 ColinD,
回答が更新されます。マルチセットであなたを誤解して申し訳ありません。 TreeMultimapsを使用してみてください。
追加された 著者 szhem,
ただし、 Multimaps.index を使用することは難しくなります。なぜなら、新しい重複戦略ごとに、新しい key クラスも作成してください。
追加された 著者 szhem,

Personクラスは、 boolean equals(Object o)を実装する必要があります。

次に、この方法で重複を見つけることができます:

You have somewhere: Collection list;

Person[] persons = list.toArray();
Integer[] duplicateOf = new Integer[persons.length];
Arrays.fill(duplicateOf, -1);

// For all the values in the Collection
for (int i = 0; i < persons.length; i++) {

 //Find the duplicate
  for (int j = 0; j < persons.length; j++) {
    if (persons[i].equals(persons[j]) && i != j)
      duplicateOf[j] = i;
  }
}

これで、 j 要素の複製は、 duplicateOf [j] というインデックスにあります。

1
追加された

personオブジェクトの.equals()をオーバーライドしてみてください。次に、各人物オブジェクト 'duplicateOf'などに新しいフィールドを追加します。

次に、配列をループして、各人を他の人と照らし合わせてチェックします。人物 'duplicateOf'フィールドがnullの場合、それをスキップします。 .equals()がtrueを返す場合、 'duplicateOf'フィールドを設定することができます。

1
追加された