Java İki Listeyi Karşılaştır


92

İki listem var (java listeleri değil, iki sütun diyebilirsiniz)

Örneğin

**List 1**            **Lists 2**
  milan                 hafil
  dingo                 iga
  iga                   dingo
  elpha                 binga
  hafil                 mike
  meat                  dingo
  milan
  elpha
  meat
  iga                   
  neeta.peeta    

Kaç öğenin aynı olduğunu döndüren bir yöntem istiyorum. Bu örnek için 3 olmalı ve bana hem listenin benzer değerlerini hem de farklı değerleri döndürmelidir.

Cevabınız evet ise hashmap kullanmalı mıyım, o zaman sonucu almak için hangi yöntem?

Lütfen yardım et

Not: Bu bir okul ödevi değil :) Yani bana rehberlik ederseniz bu yeterli olacaktır


Lütfen listenin java listesi veya hashmap veya herhangi bir veri yapısı olmadığı herhangi bir veri yapısını
önerin

1
İstisnai durumlarda ne yapmanız gerektiğini düşündüğünüzden emin olun. Listeler aynı değeri iki kez içerebilir mi? Eğer öyleyse, "dingo" her iki listede de iki kez yer alıyorsa, bu ortak iki öğe olarak mı yoksa yalnızca bir öğe olarak mı sayılır?
JavadocMD

Listeden birini değiştirebilir misin?
Anthony Forloney

nasıl düzenlenir ?? Evet, her liste birden çok kez benzer değerler içerebilir
user238384

Sorunun hemen ardından etiketlerin altında küçük bir düzenleme bağlantısı bulunmalıdır .
OscarRyz

Yanıtlar:


160

DÜZENLE

İşte iki versiyon. Biri kullanıyor ArrayListve diğeri kullanıyorHashSet

Bunları karşılaştırın ve ihtiyacınız olanı elde edene kadar bundan kendi sürümünüzü oluşturun .

Bu, aşağıdakileri kapsamak için yeterli olmalıdır:

Not: Bu bir okul ödevi değil :) Yani bana rehberlik ederseniz bu yeterli olacaktır

Sorunuzun bir parçası.

orijinal cevapla devam ederek:

Bunun için java.util.Collection ve / veya kullanabilirsiniz java.util.ArrayList.

RetainAll yöntem şunları yapar:

Yalnızca bu koleksiyondaki, belirtilen koleksiyonda bulunan öğeleri tutar

bu örneğe bakın:

import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;

public class Repeated {
    public static void main( String  [] args ) {
        Collection listOne = new ArrayList(Arrays.asList("milan","dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta"));
        Collection listTwo = new ArrayList(Arrays.asList("hafil", "iga", "binga", "mike", "dingo"));

        listOne.retainAll( listTwo );
        System.out.println( listOne );
    }
}

DÜZENLE

İkinci kısım için (benzer değerler) removeAll yöntemini kullanabilirsiniz :

Bu koleksiyonun belirtilen koleksiyonda bulunan tüm öğelerini kaldırır.

Bu ikinci sürüm size aynı zamanda benzer değerleri ve tekrarlanan tutamaçları verir (onları atarak).

Bu sefer Collectiona Setyerine a olabilir List(fark şu ki, Set tekrarlanan değerlere izin vermiyor)

import java.util.Collection;
import java.util.HashSet;
import java.util.Arrays;

class Repeated {
      public static void main( String  [] args ) {

          Collection<String> listOne = Arrays.asList("milan","iga",
                                                    "dingo","iga",
                                                    "elpha","iga",
                                                    "hafil","iga",
                                                    "meat","iga", 
                                                    "neeta.peeta","iga");

          Collection<String> listTwo = Arrays.asList("hafil",
                                                     "iga",
                                                     "binga", 
                                                     "mike", 
                                                     "dingo","dingo","dingo");

          Collection<String> similar = new HashSet<String>( listOne );
          Collection<String> different = new HashSet<String>();
          different.addAll( listOne );
          different.addAll( listTwo );

          similar.retainAll( listTwo );
          different.removeAll( similar );

          System.out.printf("One:%s%nTwo:%s%nSimilar:%s%nDifferent:%s%n", listOne, listTwo, similar, different);
      }
}

Çıktı:

$ java Repeated
One:[milan, iga, dingo, iga, elpha, iga, hafil, iga, meat, iga, neeta.peeta, iga]

Two:[hafil, iga, binga, mike, dingo, dingo, dingo]

Similar:[dingo, iga, hafil]

Different:[mike, binga, milan, meat, elpha, neeta.peeta]

Tam olarak ihtiyacınız olan şeyi yapmazsa, buradan başlayabilmeniz için size iyi bir başlangıç ​​sağlar.

Okuyucu için soru: Tekrarlanan tüm değerleri nasıl dahil edersiniz?


@Oscar, tam olarak düşündüm, ama içeriğini değiştirebilir miyiz emin değildim listOne, ama yine de +1!
Anthony Forloney

@poygenelubricants jenerik değil ham tür derken neyi kastediyorsunuz ? Neden olmasın?
OscarRyz

Oscar, güncellenmiş sorumu gördün mü? Tekrarlanan değerleri destekliyor mu?
user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/... "kesinlikle önerilmez Java programlama diline genericity girmesinden sonra yazılı kod ham tiplerinin kullanılması mümkündür gelecekteki sürümleri arasında. Java programlama dili, ham türlerin kullanımına izin vermez. "
poligenelubricants

2
@polygenelubricants yanıtı, kopyaları ve ham türleri işlemek için güncellendi. BTW, Java'nın .. gelecekteki sürümü ... asla olmayacak. ;)
OscarRyz


9

Bu listeler gerçekten mi (sıralı, kopyaları olan) yoksa kümeler mi (sırasız, kopya yok)?

Çünkü ikincisi ise, o zaman a kullanabilir java.util.HashSet<E>ve uygun olanı kullanarak bunu beklenen doğrusal zamanda yapabilirsiniz retainAll.

    List<String> list1 = Arrays.asList(
        "milan", "milan", "iga", "dingo", "milan"
    );
    List<String> list2 = Arrays.asList(
        "hafil", "milan", "dingo", "meat"
    );

    // intersection as set
    Set<String> intersect = new HashSet<String>(list1);
    intersect.retainAll(list2);
    System.out.println(intersect.size()); // prints "2"
    System.out.println(intersect); // prints "[milan, dingo]"

    // intersection/union as list
    List<String> intersectList = new ArrayList<String>();
    intersectList.addAll(list1);
    intersectList.addAll(list2);
    intersectList.retainAll(intersect);
    System.out.println(intersectList);
    // prints "[milan, milan, dingo, milan, milan, dingo]"

    // original lists are structurally unmodified
    System.out.println(list1); // prints "[milan, milan, iga, dingo, milan]"
    System.out.println(list2); // prints "[hafil, milan, dingo, meat]"

Peki hangi veri yapısının olması gerektiğini gerçekten bilmiyorum. Kopyaları var. Şimdi güncellenmiş soruyu görebilirsiniz
user238384

Tekrarlanan değerleri veri setinden kaldıracak mı? coz Herhangi bir değer kaybetmek istemiyorum :(
user238384

@agazerboy: Her iki soruyu da ele almaya çalıştım. Daha fazla açıklama istemekten çekinmeyin.
poligenelubricants

çok teşekkürler. Programınızı kopyalar ile denedim mesela ilk listeye "iga" yı iki kez ekledim ama yine de cevap olarak 3 veriyor. Şimdi 4 olması gerekirken. coz listesi 1'in 4 benzer değeri vardır. Bir girişi birden çok kez eklersem, çalışması gerekir. Ne dersin? Başka bir veri yapısı var mı?
user238384

6

Java 8 kullanımı removeIf

public int getSimilarItems(){
    List<String> one = Arrays.asList("milan", "dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta");
    List<String> two = new ArrayList<>(Arrays.asList("hafil", "iga", "binga", "mike", "dingo")); //Cannot remove directly from array backed collection
    int initial = two.size();

    two.removeIf(one::contains);
    return initial - two.size();
}

İyi görünüyor, ancak listeleri değiştirmeden tutmak istersem listelerden birini klonlamam gerekir ve bu bazı durumlarda istenmez.
Sebastian D'Agostino

6

İki koleksiyonun eşitliğini test etmenin kullanışlı bir yolunu arıyorsanız org.apache.commons.collections.CollectionUtils.isEqualCollection, sıralaması ne olursa olsun iki koleksiyonu karşılaştıran kullanabilirsiniz .


4

Tüm yaklaşımlar arasında kullanmanın org.apache.commons.collections.CollectionUtils#isEqualCollectionen iyi yaklaşım olduğunu düşünüyorum. İşte nedenleri -

  • Kendim için herhangi bir ek liste / set bildirmek zorunda değilim
  • Giriş listelerini değiştirmiyorum
  • Çok verimli. O (N) karmaşıklığındaki eşitliği kontrol eder.

apache.commons.collectionsBağımlılık olması mümkün değilse , etkinliği nedeniyle listenin eşitliğini kontrol etmek için izlediği algoritmayı uygulamanızı tavsiye ederim.


3

Basit çözüm: -

    List<String> list = new ArrayList<String>(Arrays.asList("a", "b", "d", "c"));
    List<String> list2 = new ArrayList<String>(Arrays.asList("b", "f", "c"));

    list.retainAll(list2);
    list2.removeAll(list);
    System.out.println("similiar " + list);
    System.out.println("different " + list2);

Çıktı :-

similiar [b, c]
different [f]

1

Varsayım hash1vehash2

List< String > sames = whatever
List< String > diffs = whatever

int count = 0;
for( String key : hash1.keySet() )
{
   if( hash2.containsKey( key ) ) 
   {
      sames.add( key );
   }
   else
   {
      diffs.add( key );
   }
}

//sames.size() contains the number of similar elements.

Kaç tane anahtarın aynı olduğunu değil, aynı anahtarların listesini istiyor. Bence.
Rosdi Kasim

Yardımın için teşekkürler Stefan. Evet Rosdi haklı, sen de. Toplam sayıda benzer değerlere ve benzer değerlere de ihtiyacım var.
user238384

1

Liste Karşılaştırma'da çok basit bir Liste karşılaştırması örneği buldum Bu örnek önce boyutu doğrular ve ardından bir listenin diğerindeki belirli öğenin kullanılabilirliğini kontrol eder.


-1
public static boolean compareList(List ls1, List ls2){
    return ls1.containsAll(ls2) && ls1.size() == ls2.size() ? true :false;
     }

public static void main(String[] args) {

    ArrayList<String> one = new ArrayList<String>();
    one.add("one");
    one.add("two");
    one.add("six");

    ArrayList<String> two = new ArrayList<String>();
    two.add("one");
    two.add("six");
    two.add("two");

    System.out.println("Output1 :: " + compareList(one, two));

    two.add("ten");

    System.out.println("Output2 :: " + compareList(one, two));
  }

1
Bu çözüm, ikisi "bir" in 3 kopyasını içerdiğinde yanlış sonucu döndürür. Yanlış bir şekilde gerçek bir sonuç verirdi.
Joseph Fitzgerald

Bu bölüm için teşekkürler: && ls1.size () == ls2.size ()
Nouar

1
? true :falseSnippet'inizde gerekli olduğunu düşündüğünüz herhangi bir neden var mı ?
Krzysztof Tomaszewski
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.