ArrayListにJavaの同じ要素が複数含まれているかどうかを検出(true / falseを返す)するにはどうすればよいですか?
ありがとう、テリー
編集 「ブロック」を互いに比較するのではなく、それらの整数値を比較しているわけではないことを忘れてしまいました。各「ブロック」にはintがあり、これがそれらの違いです。「getNum」という名前のメソッド(例:table1 [0] [2] .getNum();)を呼び出して、特定のブロックのintを見つけます。
ArrayListにJavaの同じ要素が複数含まれているかどうかを検出(true / falseを返す)するにはどうすればよいですか?
ありがとう、テリー
編集 「ブロック」を互いに比較するのではなく、それらの整数値を比較しているわけではないことを忘れてしまいました。各「ブロック」にはintがあり、これがそれらの違いです。「getNum」という名前のメソッド(例:table1 [0] [2] .getNum();)を呼び出して、特定のブロックのintを見つけます。
回答:
最も簡単な方法:(Set(Collection)コンストラクターまたはSet.addAllを使用して)コレクション全体をセットにダンプし、セットがArrayListと同じサイズかどうかを確認します。
List<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);
if(set.size() < list.size()){
/* There are duplicates */
}
更新:私があなたの質問を正しく理解している場合、次のようにブロックの2D配列があります
ブロックテーブル[] [];
それらの行に重複があるかどうかを検出したいですか?
その場合、Blockが「equals」と「hashCode」を正しく実装していると想定して、次のことを実行できます。
for (Block[] row : table) {
Set set = new HashSet<Block>();
for (Block cell : row) {
set.add(cell);
}
if (set.size() < 6) { //has duplicate
}
}
構文については100%確実ではないので、次のように書く方が安全かもしれません。
for (int i = 0; i < 6; i++) {
Set set = new HashSet<Block>();
for (int j = 0; j < 6; j++)
set.add(table[i][j]);
...
Set.add
追加される項目がすでにセットにある場合はブール値のfalseを返します。したがってfalse
、重複があるかどうかを知りたいだけの場合に返されるaddを短絡してベールアウトすることもできます。
Set#add
リストとセットのサイズを比較する代わりにの戻り値を使用してコードを改善
public static <T> boolean hasDuplicate(Iterable<T> all) {
Set<T> set = new HashSet<T>();
// Set#add returns false if the set does not change, which
// indicates that a duplicate element has been added.
for (T each: all) if (!set.add(each)) return true;
return false;
}
Set<T> set = new HashSet<T>(list.size());
でしょうか?リストパラメータを指定すると、リストに重複が含まれないことが一般的である場合、より効率的だと思います。
HashSet
、リストのサイズに合わせてをサイジングしても、ハッシュ構造の基本的な負荷係数のため、リスト全体を実行するとサイズが変更されます。
重複する要素を返すようにコードを改善
public static <T> List getDuplicate(Collection<T> list) {
final List<T> duplicatedObjects = new ArrayList<T>();
Set<T> set = new HashSet<T>() {
@Override
public boolean add(T e) {
if (contains(e)) {
duplicatedObjects.add(e);
}
return super.add(e);
}
};
for (T t : list) {
set.add(t);
}
return duplicatedObjects;
}
public static <T> boolean hasDuplicate(Collection<T> list) {
if (getDuplicate(list).isEmpty())
return false;
return true;
}
要素が何らかの形で比較可能である場合(順序に実際の意味があるという事実は無関心です-同等性の定義と一致している必要があるだけです)、最速の重複除去ソリューションはリストをソートします(0(n log( n)))次に、単一のパスを実行し、繰り返されるものを探します要素(つまり、互いに続く等しい要素)を(これはO(n)です)。
全体的な複雑さはO(n log(n))になります。これは、Set(n倍の長さ(n))で得られるものとほぼ同じですが、定数ははるかに小さくなります。これは、並べ替え/重複除去の定数が要素の比較のコストから生じるのに対し、セットからのコストは、ハッシュ計算と1つ(場合によっては複数)のハッシュ比較から生じる可能性が高いためです。ハッシュベースのSet実装を使用している場合、つまり、ツリーベースではO(nlog²(n))が得られるため、さらに悪い結果になります。
ただし、私が理解しているように、重複を削除する必要はありませんが、重複をテストするだけです。だから、あなたの配列にマージまたはヒープソートアルゴリズムを手動でコーディングする必要があります。それは、コンパレータが0を返した場合にtrue(つまり「dupがある」)を返すだけで終了し、そうでない場合はソートを完了し、ソートされた配列を走査して繰り返しをテストします。 。実際、マージソートまたはヒープソートでは、ソートが完了すると、両方の要素がすでに最終位置にある場合を除いて、すべての重複ペアが比較されます(これはありそうもありません)。したがって、微調整されたソートアルゴリズムにより、パフォーマンスが大幅に向上するはずです(私はそれを証明する必要がありますが、微調整されたアルゴリズムは、一様にランダムなデータのO(log(n))にあるはずです)。
に対して同様の操作を行う必要がありましたStream
が、良い例が見つかりませんでした。これが私が思いついたものです。
public static <T> boolean areUnique(final Stream<T> stream) {
final Set<T> seen = new HashSet<>();
return stream.allMatch(seen::add);
}
これには、ストリーム全体を処理する必要がなく、重複が早期に見つかった場合に短絡するという利点があり、すべてをaに入れSet
てサイズを確認するよりもはるかに複雑ではありません。したがって、このケースはおおよそ次のようになります。
List<T> list = ...
boolean allDistinct = areUnique(list.stream());
リスト内の重複を知るには、次のコードを使用します。重複を含むセットが表示されます。
public Set<?> findDuplicatesInList(List<?> beanList) {
System.out.println("findDuplicatesInList::"+beanList);
Set<Object> duplicateRowSet=null;
duplicateRowSet=new LinkedHashSet<Object>();
for(int i=0;i<beanList.size();i++){
Object superString=beanList.get(i);
System.out.println("findDuplicatesInList::superString::"+superString);
for(int j=0;j<beanList.size();j++){
if(i!=j){
Object subString=beanList.get(j);
System.out.println("findDuplicatesInList::subString::"+subString);
if(superString.equals(subString)){
duplicateRowSet.add(beanList.get(j));
}
}
}
}
System.out.println("findDuplicatesInList::duplicationSet::"+duplicateRowSet);
return duplicateRowSet;
}
この問題を処理する最良の方法は、HashSetを使用することです。
ArrayList<String> listGroupCode = new ArrayList<>();
listGroupCode.add("A");
listGroupCode.add("A");
listGroupCode.add("B");
listGroupCode.add("C");
HashSet<String> set = new HashSet<>(listGroupCode);
ArrayList<String> result = new ArrayList<>(set);
結果の配列リストを印刷して 、重複なしで結果を確認するだけです:)
重複する値のセットが必要な場合:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FindDuplicateInArrayList {
public static void main(String[] args) {
Set<String> uniqueSet = new HashSet<String>();
List<String> dupesList = new ArrayList<String>();
for (String a : args) {
if (uniqueSet.contains(a))
dupesList.add(a);
else
uniqueSet.add(a);
}
System.out.println(uniqueSet.size() + " distinct words: " + uniqueSet);
System.out.println(dupesList.size() + " dupesList words: " + dupesList);
}
}
また、場合によっては、値のトリミングや小文字の使用も検討してください。
String tempVal = null;
for (int i = 0; i < l.size(); i++) {
tempVal = l.get(i); //take the ith object out of list
while (l.contains(tempVal)) {
l.remove(tempVal); //remove all matching entries
}
l.add(tempVal); //at last add one entry
}
注:リストの先頭からアイテムが削除されるため、これによりパフォーマンスが大幅に低下します。これに対処するには、2つのオプションがあります。1)逆の順序で繰り返し、要素を削除します。2)ArrayListの代わりにLinkedListを使用します。他のコレクションを使用せずにリストから重複を削除するようにインタビューで偏った質問のため、上記の例が答えです。ただし、現実の世界では、これを達成する必要がある場合は、要素をリストからセットに配置するだけです。
/**
* Method to detect presence of duplicates in a generic list.
* Depends on the equals method of the concrete type. make sure to override it as required.
*/
public static <T> boolean hasDuplicates(List<T> list){
int count = list.size();
T t1,t2;
for(int i=0;i<count;i++){
t1 = list.get(i);
for(int j=i+1;j<count;j++){
t2 = list.get(j);
if(t2.equals(t1)){
return true;
}
}
}
return false;
}
オーバーライドした具象クラスの例equals()
:
public class Reminder{
private long id;
private int hour;
private int minute;
public Reminder(long id, int hour, int minute){
this.id = id;
this.hour = hour;
this.minute = minute;
}
@Override
public boolean equals(Object other){
if(other == null) return false;
if(this.getClass() != other.getClass()) return false;
Reminder otherReminder = (Reminder) other;
if(this.hour != otherReminder.hour) return false;
if(this.minute != otherReminder.minute) return false;
return true;
}
}
ArrayList<String> withDuplicates = new ArrayList<>();
withDuplicates.add("1");
withDuplicates.add("2");
withDuplicates.add("1");
withDuplicates.add("3");
HashSet<String> set = new HashSet<>(withDuplicates);
ArrayList<String> withoutDupicates = new ArrayList<>(set);
ArrayList<String> duplicates = new ArrayList<String>();
Iterator<String> dupIter = withDuplicates.iterator();
while(dupIter.hasNext())
{
String dupWord = dupIter.next();
if(withDuplicates.contains(dupWord))
{
duplicates.add(dupWord);
}else{
withoutDupicates.add(dupWord);
}
}
System.out.println(duplicates);
System.out.println(withoutDupicates);