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

Ответы:


160

РЕДАКТИРОВАТЬ

Вот две версии. Одно использование, ArrayListа другое использованиеHashSet

Сравните их и создайте из этого свою собственную версию, пока не получите то, что вам нужно.

Этого должно быть достаточно, чтобы покрыть:

PS: Это не школьное задание :) Так что если вы меня просто поможете, этого будет достаточно

часть вашего вопроса.

продолжая исходный ответ:

Вы можете использовать java.util.Collection и / или java.util.ArrayListдля этого.

Метод keepAll выполняет следующие действия:

Сохраняет только те элементы в этой коллекции, которые содержатся в указанной коллекции.

см. этот образец:

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 :

Удаляет все элементы этой коллекции, которые также содержатся в указанной коллекции.

Эта вторая версия дает вам также аналогичные значения и повторяет дескрипторы (отбрасывая их).

На этот раз вместо a Collectionможет быть a (разница в том, что Set не позволяет повторять значения)SetList

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 04

37

Можно попробовать intersection()и subtract()методы из CollectionUtils.

intersection()Метод дает вам коллекцию, содержащую общие элементы, а subtract()метод дает вам все необычные.

Им также следует позаботиться об аналогичных элементах


6
Следует отметить, что для этого решения требуется Apache Ccommons
Sir Codesalot

9

Действительно ли это списки (упорядоченные, с дубликатами) или наборы (неупорядоченные, без дубликатов)?

Потому что, если это последнее, то вы можете использовать, скажем, a 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
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.