Java เปรียบเทียบสองรายการ


92

ฉันมีสองรายการ (ไม่ใช่รายการ java คุณสามารถพูดได้สองคอลัมน์)

ตัวอย่างเช่น

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

ฉันต้องการวิธีที่ส่งคืนจำนวนองค์ประกอบที่เหมือนกัน สำหรับตัวอย่างนี้ควรเป็น 3 และควรคืนค่าที่คล้ายกันของทั้งสองรายการและค่าที่ต่างกันด้วย

ฉันควรใช้แฮชแมปหรือไม่ถ้าใช่แล้วจะได้ผลลัพธ์อย่างไร

กรุณาช่วย

PS: ไม่ใช่งานมอบหมายของโรงเรียน :) ดังนั้นหากคุณเพียงแค่แนะนำฉันก็เพียงพอแล้ว


โปรดแนะนำโครงสร้างข้อมูลใด ๆ รายการไม่ใช่รายการ java หรือแฮชแมปหรือโครงสร้างข้อมูลใด ๆ
user238384

1
อย่าลืมคิดถึงสิ่งที่คุณควรทำในกรณีพิเศษ รายการสามารถมีค่าเดียวกันสองครั้งได้หรือไม่ ถ้าเป็นเช่นนั้นหาก "dingo" อยู่ในทั้งสองรายการสองครั้งสิ่งนั้นจะนับเป็นสององค์ประกอบที่เหมือนกันหรือเพียงรายการเดียว
JavadocMD

คุณสามารถแก้ไขรายการใดรายการหนึ่งได้หรือไม่?
Anthony Forloney

แก้ไขยังไง ?? ใช่แต่ละรายการสามารถมีค่าที่คล้ายกันได้หลายครั้ง
user238384

ควรมีลิงก์แก้ไขเล็ก ๆ อยู่หลังคำถามด้านล่างแท็ก
OscarRyz

คำตอบ:


160

แก้ไข

นี่คือสองเวอร์ชัน หนึ่งโดยใช้ArrayListและอื่น ๆ โดยใช้HashSet

เปรียบเทียบและสร้างเวอร์ชันของคุณเองจากสิ่งนี้จนกว่าคุณจะได้สิ่งที่ต้องการ

ควรจะเพียงพอที่จะครอบคลุม:

PS: ไม่ใช่งานมอบหมายของโรงเรียน :) ดังนั้นหากคุณเพียงแค่แนะนำฉันก็เพียงพอแล้ว

ส่วนหนึ่งของคำถามของคุณ

ดำเนินการต่อด้วยคำตอบเดิม:

คุณอาจใช้java.util.Collection และ / หรือ java.util.ArrayListเพื่อสิ่งนั้น

retainAllวิธีการทำดังต่อไปนี้:

เก็บเฉพาะองค์ประกอบในคอลเล็กชันนี้ที่มีอยู่ในคอลเล็กชันที่ระบุ

ดูตัวอย่างนี้:

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

แก้ไข

สำหรับส่วนที่สอง (ค่าใกล้เคียงกัน) คุณสามารถใช้เมธอดremoveAll :

ลบองค์ประกอบทั้งหมดของคอลเล็กชันนี้ที่มีอยู่ในคอลเล็กชันที่ระบุด้วย

เวอร์ชันที่สองนี้ให้ค่าที่คล้ายกันและจัดการซ้ำ ๆ (โดยการทิ้ง)

คราวนี้Collectionอาจเป็น a SetแทนList(ความแตกต่างคือ Set ไม่อนุญาตให้มีค่าซ้ำ)

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

เอาท์พุต:

$ 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]

หากไม่ตรงตามที่คุณต้องการก็จะเป็นการเริ่มต้นที่ดีเพื่อให้คุณจัดการได้จากที่นี่

คำถามสำหรับผู้อ่าน: คุณจะรวมค่าซ้ำทั้งหมดได้อย่างไร?


@Oscar ความคิดที่แน่นอนของฉัน แต่ฉันไม่แน่ใจว่าเราสามารถแก้ไขเนื้อหาของlistOneแต่ +1 ได้อย่างไร!
Anthony Forloney

@poygenelubricants ประเภทดิบไม่ใช่ยาชื่อสามัญหมายความว่าอย่างไร ทำไมจะไม่ล่ะ?
OscarRyz

ออสการ์คุณเห็นคำถามล่าสุดของฉันไหม รองรับค่าซ้ำหรือไม่?
user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "การใช้ประเภทดิบในโค้ดที่เขียนขึ้นหลังจากการนำความเป็นสามัญเข้าสู่ภาษาการเขียนโปรแกรม Java เป็นเรื่องที่ไม่ควรอย่างยิ่งเป็นไปได้ว่าเวอร์ชันในอนาคตของ ภาษาโปรแกรม Java จะไม่อนุญาตให้ใช้ประเภทดิบ "
polygenelubricants

2
คำตอบของ @polygenelubricants อัปเดตเพื่อรองรับรายการที่ซ้ำกันและประเภทดิบ BTW .. Java เวอร์ชันอนาคต ...จะไม่มีวันเกิดขึ้น ;)
OscarRyz

37

คุณสามารถลองintersection()และวิธีการจากsubtract()CollectionUtils

intersection()method ช่วยให้คุณมีคอลเลกชันที่มีองค์ประกอบทั่วไปและsubtract()วิธีนี้จะให้สิ่งที่ผิดปกติทั้งหมดแก่คุณ

พวกเขาควรดูแลองค์ประกอบที่คล้ายกันด้วย


6
ควรทราบว่าโซลูชันนี้ต้องใช้ Apache Ccommons
Sir Codesalot

9

รายการเหล่านี้เป็นรายการจริง ๆ(เรียงลำดับมีรายการที่ซ้ำกัน) หรือเป็นชุด (ไม่เรียงลำดับไม่มีรายการซ้ำ)

เพราะถ้าเป็นหลังแล้วคุณสามารถใช้การพูดและทำเช่นนี้ในเส้นเวลาที่คาดว่าจะใช้สะดวกjava.util.HashSet<E>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]"

ฉันไม่รู้จริงๆว่าควรเป็นโครงสร้างข้อมูลแบบไหน มีรายการที่ซ้ำกัน ตอนนี้คุณสามารถดูคำถามที่อัปเดตแล้ว
user238384

จะลบค่าซ้ำออกจากชุดข้อมูลหรือไม่? เพราะฉันไม่ต้องการสูญเสียมูลค่าใด ๆ :(
user238384

@agazerboy: ฉันพยายามตอบคำถามทั้งสองข้อแล้ว อย่าลังเลที่จะขอคำชี้แจงเพิ่มเติม
polygenelubricants

ขอบคุณโพลี ฉันลองใช้โปรแกรมของคุณโดยมีรายการที่ซ้ำกันเช่นในรายการแรกฉันเพิ่ม "iga" สองครั้ง แต่ก็ยังส่งคืน 3 เป็นคำตอบให้ฉัน ในขณะที่ควรจะเป็น 4 ตอนนี้ coz list 1 มีค่าใกล้เคียงกัน 4 ค่า หากฉันเพิ่มรายการเดียวหลายครั้งก็ควรใช้งานได้ พูดว่าอะไรนะ? โครงสร้างข้อมูลอื่น ๆ ?
user238384

6

ใช้ java 8 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();
}

มันดูดี แต่ถ้าฉันต้องการเก็บรายการไว้โดยไม่มีการแก้ไขฉันจะต้องโคลนรายการใดรายการหนึ่งและไม่เป็นที่ต้องการในบางกรณี
Sebastian D'Agostino

6

หากคุณกำลังมองหาวิธีที่สะดวกในการทดสอบความเท่าเทียมกันของสองคอลเลกชั่นคุณสามารถใช้org.apache.commons.collections.CollectionUtils.isEqualCollectionซึ่งจะเปรียบเทียบสองคอลเลคชันโดยไม่คำนึงถึงลำดับ


4

จากวิธีการทั้งหมดฉันพบว่าการใช้org.apache.commons.collections.CollectionUtils#isEqualCollectionเป็นแนวทางที่ดีที่สุด นี่คือเหตุผล -

  • ฉันไม่ต้องประกาศรายการเพิ่มเติม / ตั้งค่าตัวเอง
  • ฉันไม่ได้เปลี่ยนรายการอินพุต
  • มันมีประสิทธิภาพมาก ตรวจสอบความเท่าเทียมกันในความซับซ้อน O (N)

หากไม่สามารถapache.commons.collectionsพึ่งพาได้ฉันขอแนะนำให้ใช้อัลกอริทึมดังต่อไปนี้เพื่อตรวจสอบความเท่าเทียมกันของรายการเนื่องจากประสิทธิภาพของมัน


3

วิธีง่ายๆ: -

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

เอาท์พุท: -

similiar [b, c]
different [f]

1

สมมติhash1และhash2

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.

เขาต้องการรายการคีย์ที่เหมือนกันไม่ใช่จำนวนคีย์ที่เหมือนกัน ฉันคิด.
Rosdi Kasim

ขอบคุณ Stefan สำหรับความช่วยเหลือของคุณ ใช่ Rosdi ถูกต้องและคุณเช่นกัน ฉันต้องการจำนวนรวมของค่าที่คล้ายกันและค่าที่คล้ายกันเช่นกัน
user238384

1

ฉันพบตัวอย่างพื้นฐานของการเปรียบเทียบรายการที่เปรียบเทียบรายการ ตัวอย่างนี้จะตรวจสอบขนาดก่อนแล้วจึงตรวจสอบความพร้อมใช้งานขององค์ประกอบเฉพาะของรายการหนึ่งในอีกรายการหนึ่ง


-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
วิธีนี้จะส่งคืนผลลัพธ์ที่ไม่ถูกต้องเมื่อสองรายการมี "หนึ่ง" 3 ชุด มันจะให้ผลลัพธ์ที่แท้จริงอย่างไม่ถูกต้อง
Joseph Fitzgerald

ขอบคุณสำหรับส่วนนี้: && ls1.size () == ls2.size ()
Nouar

1
เหตุผลใดที่คุณคิดว่า? true :falseจำเป็นสำหรับข้อมูลโค้ดของคุณ
Krzysztof Tomaszewski
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.