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.