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, і він повинен повернути мені подібні значення як списку, так і різні значення.

Чи повинен я використовувати hashmap, якщо так, то який метод отримати мій результат?

Будь ласка, допоможіть

PS: Це не шкільне завдання :) Тож, якщо ви просто направите мене, цього буде достатньо


Будь ласка, запропонуйте будь-яку структуру даних, список не є списком Java або хеш-картою або будь-якою структурою даних
— user238384

1
Обов’язково подумайте, що робити у виняткових випадках. Чи можуть списки двічі містити одне і те ж значення? Якщо так, то якщо "динго" двічі є в обох списках, чи це зараховується як два спільні елементи чи лише один?
— JavadocMD

Чи можете ви змінити один зі Списку?
— Ентоні Форлоні

як редагувати ?? Так, кожен список може містити подібні значення кілька разів
— user238384

Відразу після запитання під тегами має бути посилання для редагування .
— OscarRyz

Відповіді:


159

РЕДАГУВАТИ

Ось дві версії. Один використовує, ArrayListа інший використовуєHashSet

Порівняйте їх і створіть свою власну версію з цього, поки не отримаєте те, що вам потрібно.

Цього має бути достатньо для покриття:

PS: Це не шкільне завдання :) Тож, якщо ви просто направите мене, цього буде достатньо

частина вашого запитання.

продовжуючи оригінальну відповідь:

Ви можете використовувати a 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може бути Setзамість a 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!
— Ентоні Форлоні

@poygenelubricants що ви маєте на увазі під сировинними типами, а не дженериками? Чому ні?
— OscarRyz

Оскаре, ти бачив моє оновлене запитання? Чи підтримує він повторювані значення?
— user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "Використання необроблених типів у коді, написаному після введення загального в мову програмування Java, настійно не рекомендується. Можливо, майбутні версії мова програмування Java заборонить використання необроблених типів ".
— полігенмастильні матеріали

2
Відповідь @polygenelubricants оновлена, щоб обробляти дублікати та необроблені типи. До речі, .. майбутня версія Java ... ніколи не відбудеться. ;)
— OscarRyz

37

Ви можете спробувати intersection()і subtract()методи від CollectionUtils.

intersection()method дає вам колекцію, що містить загальні елементи, а subtract()метод - усі незвичні.

Вони також повинні подбати про подібні елементи


6
Слід зазначити, що для цього рішення потрібен Apache Ccommons
— сер Кодесалот,

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

Чи видалить повторювані значення з набору даних? coz Я не хочу
— втрачати

@agazerboy: Я намагався розглянути обидва питання. Не соромтеся запитувати додаткові роз’яснення.
— полігенмастильні матеріали

спасибі полі. Я спробував вашу програму з дублікатами, наприклад, у першому списку я двічі додав "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();
}

Це виглядає добре, але якщо я хочу залишити списки незмінними, мені довелося б клонувати один зі списків, і це не було б бажаним у певних випадках.
— Себастьян Д'Агостіно,

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.

Йому потрібен список однакових ключів, а не скільки однакових ключів. Я думаю.
— Росді Касім

Дякуємо Стефану за допомогу. Так, Росді прав, і ти також. Мені також потрібна загальна кількість подібних значень та подібних значень.
— user238384

1

Я знайшов дуже базовий приклад порівняння списку в List Compare Цей приклад спочатку перевіряє розмір, а потім перевіряє наявність певного елемента одного списку в іншому.


-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 копії "одного". Це неправильно дало б справжній результат.
— Джозеф Фіцджеральд,

Дякуємо за цю частину: && ls1.size () == ls2.size ()
— Nouar

1
Будь-яка причина, яка, на вашу думку ? true :false, потрібна у вашому фрагменті?
— Кшиштоф Томашевський
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.