जावा: ArrayList में डुप्लिकेट का पता लगाएं?


104

मैं पता लगाने के बारे में कैसे जा सकता हूं (सही / गलत लौटना) कि क्या एक ArrayList में जावा में एक ही तत्व से अधिक है?

बहुत धन्यवाद, टेरी

संपादन यह उल्लेख करना भूल गया कि मैं "ब्लॉक" की एक दूसरे के साथ तुलना नहीं कर रहा हूँ, लेकिन उनके पूर्णांक मान। प्रत्येक "ब्लॉक" में एक इंट होता है और यही वह है जो उन्हें अलग बनाता है। मुझे "getNum" (उदाहरण के लिए table1 [0] [2] .getNum ()) नामक विधि द्वारा एक विशेष ब्लॉक का उदाहरण मिलता है;


यदि "ब्लॉक" की तुलना किसी इंट से की जाती है, तो आपको संभवत: हैशकोड लौटा देना चाहिए और उसी इंट के बराबर होते हैं।
पॉल टॉम्बलिन

सूची के बजाय सेट का उपयोग करें
dmarquina

जवाबों:


192

सरलतम: पूरे संग्रह को एक सेट (सेट (संग्रह) निर्माणकर्ता या सेट.एडएड का उपयोग करके) में डंप करें, फिर देखें कि सेट का ArrayList के समान आकार है या नहीं।

List<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);

if(set.size() < list.size()){
    /* There are duplicates */
}

अपडेट: यदि मैं आपके प्रश्न को सही ढंग से समझ रहा हूं, तो आपके पास ब्लॉक के रूप में 2d सरणी है

ब्लॉक तालिका [] [];

और अगर आप उनमें से किसी भी पंक्ति डुप्लिकेट है पता लगाना चाहते हैं?

उस मामले में, मैं निम्नलिखित कर सकता हूं, यह मानते हुए कि ब्लॉक "बराबर" और "हैशकोड" को सही ढंग से लागू करता है:

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अगर आप जानना चाहते हैं तो क्या कोई डुप्लिकेट है।


13
हैशकोड / समान लागू करना सुनिश्चित करें।
jon077

1
या यहां तक ​​कि थोड़ा आसान: सेट बनाते समय इसे लपेटें, जैसे कि AddAll का उपयोग करने के बजाय, नया हैशसेट (सूची)।
फेबियन स्टिग

2
@ jon077: यह "डुप्लिकेट" की आपकी परिभाषा पर निर्भर करता है।
माइकल मायर्स

2 डी सरणी में तत्वों का पता लगाने की प्रक्रिया समान होगी? उदाहरण के लिए, सरणी [0] [0] से सरणी [0] [6] (एक 'पंक्ति') की जाँच ..? बहुत धन्यवाद, टेरी

सरणी में प्रत्येक ऑब्जेक्ट एक पूर्णांक मान रखता है। "डुप्लिकेट" द्वारा, ऑब्जेक्ट का पूर्णांक मान होगा।

60

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;
}

7
क्या HashSet को यह बताने के लिए अधिक कुशल होगा कि कितना स्थान आवंटित किया जाए Set<T> set = new HashSet<T>(list.size());:? सूची पैरामीटर को देखते हुए मुझे लगता है कि यह अधिक कुशल है अगर सूची में डुप्लिकेट को शामिल नहीं करना सामान्य है।
पॉल जैक्सन

1
पूरी सूची के आधार पर @PaJJackson Sizing शायद फायदेमंद होगा। हालाँकि यदि सामान्य मामला इसके लिए एक डुप्लिकेट जल्दी खोजने के लिए है तो अंतरिक्ष बर्बाद हो गया था। HashSetसूची के आकार के अंतर्निहित लोडिंग कारक की वजह से पूरी सूची में चलने पर भी आकार के अनुसार सूची के आकार को आकार देने में परिणाम होगा।
जय एंडरसन

1
जब तक आप रनटाइम या स्पेस के साथ वास्तविक मुद्दों का अनुभव नहीं करेंगे, मैं उस तरह से आपके कोड को समाप्त नहीं करूंगा। समय से पहले अनुकूलन से बचा जाता है।
अनकुहन

15

यदि आप बिल्कुल भी डुप्लिकेट होने से बचना चाहते हैं, तो आपको केवल डुप्लिकेट का पता लगाने की मध्य प्रक्रिया को काट देना चाहिए और सेट का उपयोग करना चाहिए ।



@ jon077: जरूरी नहीं, जैसा मैंने अभी कहा।
माइकल मायर्स

1
हालाँकि सेट का उपयोग करने से डुप्लिकेट का पता नहीं चलता है । यह सिर्फ उन्हें रोकता है। जब तक आप ऊपर @akuhn द्वारा उल्लिखित विधि जोड़ने के परिणाम की जांच नहीं करते।
mcallahan

13

डुप्लिकेट तत्वों को वापस करने के लिए बेहतर कोड

  • एक संग्रह में डुप्लिकेट पा सकते हैं
  • डुप्लिकेट का सेट लौटाएं
  • सेट से अद्वितीय तत्व प्राप्त किए जा सकते हैं

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;
}

यह बहुत बढ़िया है। आपके पास कुछ अमान्य कोड हैं, और शायद यह सबसे इष्टतम तरीका नहीं है, लेकिन आपका दृष्टिकोण पूरी तरह से चट्टानों का है! (और यह बहुत अच्छा काम करता है)
जूल्स कॉलल

9

यदि आपके तत्व किसी भी तरह से तुलनीय हैं (यह तथ्य कि ऑर्डर का कोई वास्तविक अर्थ उदासीन है - इसे बस आपकी समानता की परिभाषा के अनुरूप होना चाहिए), सबसे तेज़ डुप्लिकेट हटाने का समाधान सूची को सॉर्ट करने वाला है (0 (एन लॉग) n))) फिर एक एकल पास करने के लिए और दोहराया तत्वों (यानी, समान तत्व जो एक दूसरे का अनुसरण करते हैं) की तलाश करते हैं (यह ओ (n) है)।

समग्र जटिलता ओ (एन लॉग (एन)) होने जा रही है, जो लगभग एक सेट (एन गुना लंबा (एन)) के साथ क्या मिलेगा, लेकिन बहुत छोटे निरंतर के साथ है। ऐसा इसलिए है क्योंकि तत्वों की तुलना के आधार पर छंटनी / कटौती परिणाम में निरंतर है, जबकि सेट से लागत एक हैश गणना से परिणाम की संभावना है, प्लस एक (संभवतः कई) हैश तुलना। यदि आप हैश-आधारित सेट कार्यान्वयन का उपयोग कर रहे हैं, तो यह है, क्योंकि एक ट्री आधारित आपको O (n log) (n)) देने जा रहा है, जो कि और भी बुरा है।

जैसा कि मैं इसे समझता हूं, हालांकि, आपको डुप्लिकेट को हटाने की आवश्यकता नहीं है , लेकिन केवल उनके अस्तित्व के लिए परीक्षण करें। तो आपको अपने एरे पर एक मर्ज या हीप सॉर्ट अल्गोरिदम को हाथ से कोड करना चाहिए, जो कि यदि आपका तुलनित्र 0 लौटाता है, तो वह सही (यानी "वहाँ एक डुबकी") वापस लौटता है, और अन्यथा सॉर्ट को पूरा करता है, और पुनरावृत्ति के लिए सॉर्ट किए गए एरे परीक्षण का पता लगाता है। । मर्ज या हीप सॉर्ट में, वास्तव में, जब सॉर्ट पूरा हो जाता है, तो आप हर डुप्लिकेट जोड़ी की तुलना करेंगे जब तक कि दोनों तत्व पहले से ही अपने अंतिम स्थान पर नहीं थे (जो कि संभावना नहीं है)। इस प्रकार, एक tweaked एल्गोरिथ्म एक विशाल प्रदर्शन में सुधार करना चाहिए (मुझे यह साबित करना होगा, लेकिन मुझे लगता है कि tweaked एल्गोरिथ्म समान रूप से यादृच्छिक डेटा पर O (लॉग (n)) में होना चाहिए)


इस मामले में, n 6 है इसलिए मैं कार्यान्वयन विवरणों पर बहुत समय बर्बाद नहीं करूंगा, लेकिन अगर मैं कभी भी ऐसा कुछ करने की आवश्यकता हूं तो मैं आपके विचार को विशेष ढेर के प्रकार पर रखूंगा।
पॉल टॉम्बलिन

मैं तीसरे पैराग्राफ को नहीं समझता। जैसा कि आप लिखते हैं, मर्जेसट और हेस्पोर्ट दोनों ओ (नॉगल (एन)) हैं, ओ (लॉग (एन)) नहीं; यहां तक ​​कि अगर आप एक बार डुप्लिकेट की पहचान करने से बाहर निकल जाते हैं, तो भी यह आपके समय की जटिलता को नहीं बदलता है ...
ChaimKut

8

मैं एक के लिए एक समान ऑपरेशन करने की जरूरत है Stream, लेकिन एक अच्छा उदाहरण नहीं मिल सकता है। यहाँ मैं क्या लेकर आया हूँ।

public static <T> boolean areUnique(final Stream<T> stream) {
    final Set<T> seen = new HashSet<>();
    return stream.allMatch(seen::add);
}

शॉर्ट-सर्कुलेटिंग का फायदा तब होता है जब डुप्लिकेट्स को पूरी स्ट्रीम प्रोसेस करने के बजाय जल्दी मिल जाते हैं और सब कुछ डालने Setऔर साइज चेक करने की तुलना में ज्यादा जटिल नहीं होता है। तो यह मामला मोटे तौर पर होगा:

List<T> list = ...
boolean allDistinct = areUnique(list.stream());

7

जावा 8+ के साथ आप स्ट्रीम एपीआई का उपयोग कर सकते हैं:

boolean areAllDistinct(List<Block> blocksList) {
    return blocksList.stream().map(Block::getNum).distinct().count() == blockList.size();
}

2

सीधे शब्दों में कहें: 1) सुनिश्चित करें कि सभी आइटम तुलनीय हैं 2) सरणी 2 को सॉर्ट करें) सरणी पर पुनरावृत्त करें और डुप्लिकेट ढूंढें


1

सूची में डुप्लिकेट जानने के लिए निम्नलिखित कोड का उपयोग करें: यह आपको वह सेट देगा जिसमें डुप्लिकेट शामिल हैं।

 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;
  }

1

इस समस्या को हल करने का सबसे अच्छा तरीका है एक हैशसेट का उपयोग करना :

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);

परिणाम परिणाम सूची को प्रिंट करें और डुप्लिकेट के बिना परिणाम देखें :)


1

यदि आप डुप्लिकेट मानों का सेट चाहते हैं:

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);
    }
}

और शायद मानों को ट्रिम करने या लोअरकेस का उपयोग करने के बारे में भी सोचें ... आपके मामले पर निर्भर करता है।


यदि आप डुप्लिकेट चाहते हैं तो सबसे सरल और सबसे अच्छा जवाब, प्रदर्शन के लिए आप आर्गन्स के आकार के साथ अनूठे संकेत का संकेत दे सकते हैं।
क्रिस्टोफ़ रूसो

0
    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
    }

नोट: यह प्रमुख प्रदर्शन हिट होगा, क्योंकि आइटम को सूची के प्रारंभ से हटा दिया जाता है। इसे संबोधित करने के लिए, हमारे पास दो विकल्प हैं। 1) रिवर्स ऑर्डर में पुनरावृति और तत्वों को हटा दें। 2) ArrayList के बजाय लिंक्डलिस्ट का उपयोग करें। किसी अन्य संग्रह का उपयोग किए बिना सूची से डुप्लिकेट को हटाने के लिए साक्षात्कार में पूछे गए पक्षपाती प्रश्नों के कारण, उदाहरण के लिए उत्तर है। वास्तविक दुनिया में, अगर मुझे इसे हासिल करना है, तो मैं सूची से सेट तक के तत्वों को सरल रखूंगा!


0
/**
     * 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;
    }
}

0
    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);

जवाब के साथ कुछ स्पष्टीकरण जोड़ें कि यह उत्तर ओपी को वर्तमान मुद्दे को ठीक करने में कैसे मदद करता है
ρяєρ withя K

0

यह जवाब कोटलिन में लिखा गया है, लेकिन आसानी से जावा में अनुवाद किया जा सकता है।

यदि आपकी सरणी सूची का आकार एक निश्चित छोटी सीमा के भीतर है, तो यह एक महान समाधान है।

var duplicateDetected = false
    if(arrList.size > 1){
        for(i in 0 until arrList.size){
            for(j in 0 until arrList.size){
                if(i != j && arrList.get(i) == arrList.get(j)){
                    duplicateDetected = true
                }
            }
        }
    }

0
private boolean isDuplicate() {
    for (int i = 0; i < arrayList.size(); i++) {
        for (int j = i + 1; j < arrayList.size(); j++) {
            if (arrayList.get(i).getName().trim().equalsIgnoreCase(arrayList.get(j).getName().trim())) {
                return true;
            }
        }
    }

    return false;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.