Найти отсутствующие элементы из Arraylist в Java

Привет, я новичок в java и пробовал свои силы в части коллекций, у меня есть простой запрос, у меня есть два списка массивов, скажем, объект сотрудника

class Employee
{
    private int emp_id;
    private String name;
    private List<String> mobile_numbers;

    //.....getters and setters
}

скажем, listA и listB имеют следующие данные

    List<Employee> listA = new ArrayList<Employee>(); 
    List<Employee> listB = new ArrayList<Employee>(); 

    listA.add(new Employee("101", "E1", listOfMobileNumbers));
    listA.add(new Employee("102", "E2", listOfMobileNumbers1));
    listA.add(new Employee("103", "E3", listOfMobileNumbers2));
    listA.add(new Employee("104", "E4", listOfMobileNumber4));
    listA.add(new Employee("105", "E5", listOfMobileNumbers5));

    listB.add(new Employee("101", "E1", listOfMobileNumbers1));
    listB.add(new Employee("102", "E2", listOfMobileNumbers2));
    listB.add(new Employee("106", "E6", listOfMobileNumber6));
    listB.add(new Employee("107", "E7", listOfMobileNumber7));
    listB.add(new Employee("108", "E8", listOfMobileNumbers8));

где listOfMobileNumbers - это List<String>

Теперь я хочу найти дополнительные элементы из списка людей. т.е.

 List<Employee> additionalDataInListA = new ArrayList<Employee>(); 
    // this list should contain 103, 104 and 105

  List<Employee> additionalDataInListB= new ArrayList<Employee>(); 
    // this list should contain 106, 107 and 108               

Как мне этого добиться?

Ваша помощь очень ценится.

Редактировать:

Я не хочу использовать какие-либо внутренние функции, я хочу добиться этого, написав некоторую ручную функцию сравнения.

Я также не могу переопределить функцию equals, потому что в моем случае использования у меня есть FieldNo, которое является int, и Values ​​, которое является List<String>.

количество вхождений поля «n» раз, и каждый раз значения, связанные с этим полем, будут разными.

Например: FieldNo = 18 Values ​​= ["A"];

FieldNo = 18 значений = ["B"]; и так далее ...

Идентификатор сотрудника, который я использовал, был использован только в целях иллюстрации, где имеет смысл переопределить равенство и хэш-код.


person user2437809    schedule 10.06.2013    source источник
comment
что ты уже испробовал? Вы сравнивали Employees? Выполняли какую-либо итерацию по списку?   -  person thegrinner    schedule 10.06.2013
comment
возможный дубликат Как объединять, пересекать, различать и менять местами данные в java   -  person Stijn Geukens    schedule 10.06.2013
comment
@ user2437809 Пожалуйста, посмотрите мое решение с использованием библиотек lambdaj и hamcrest (это можно сделать в несколько строк).   -  person Gaston Flores    schedule 10.06.2013


Ответы (7)


Вы можете использовать boolean removeAll(Collection<?> c) метод.

Просто обратите внимание, что этот метод изменяет List, на котором вы его вызываете. Если вы сохраните исходный List нетронутым, вам придется сначала сделать копию списка, а затем метод копии.

e.g.

List<Employee> additionalDataInListA = new ArrayList<Employee>(listA);
additionalDataInListA.removeAll(listB);
person Bhesh Gurung    schedule 10.06.2013
comment
Также требуется, чтобы equals() и hashCode() были переопределены в классе Employee. - person GriffeyDog; 10.06.2013
comment
@GriffeyDog: Вы правы, это основное требование, которое должны выполнять объекты, чтобы коллекция (и) работала должным образом. - person Bhesh Gurung; 10.06.2013

Переопределите equals в Employee, чтобы проверить равенство между идентификаторами (и помните, что при переопределении equals вы также должны переопределить hashCode). Потом:

List<Employee> additionalDataInListA = new ArrayList<Employee>(listA);
additionalDataInListA.removeAll(listB);

List<Employee> additionalDataInListB = new ArrayList<Employee>(listB);
additionalDataInListB.removeAll(listA);

Соответствующая документация:

person arshajii    schedule 10.06.2013

Вы можете использовать метод removeAll интерфейса Collection, как показано в верхнем ответе на этот вопрос (как я могу рассчитать разницу между двумя списками ArrayList?).

person David Futcher    schedule 10.06.2013

Вы можете использовать lambdaj (скачать здесь, веб-сайт) и hamcrest (скачать здесь, веб-сайт), это библиотеки очень эффективны для управления коллекциями, следующий код очень прост и отлично работает. С помощью этих библиотек вы можете решить вашу проблему в одну строку. Вы должны добавить в свой проект: hamcrest-all-1.3.jar и lambdaj-2.4.jar. Надеюсь, эта помощь пригодится.

import static ch.lambdaj.Lambda.filter;
import static ch.lambdaj.Lambda.having;
import static ch.lambdaj.Lambda.on;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.not;

public class Test2{
        public static void main(String[] args) {
            List<String> oldNames =  Arrays.asList("101","102","103","104","105");
            List<String> newNames = Arrays.asList("101","102","106","107","108");

            List<String> newList = filter(not(having(on(String.class), isIn(oldNames))),newNames);
            List<String> newList2 = filter(not(having(on(String.class), isIn(newNames))),oldNames);
            System.out.println(newList);
            System.out.println(newList2);
            /*out
            [106, 107, 108]
            [103, 104, 105]
            */
    }
}

Этот пример работает с простым списком строк, но может быть адаптирован для вашего объекта Employee.

person Gaston Flores    schedule 10.06.2013

for(int j = 0; j < listB.size(); j++){
   if (!listA.contains(listB.get(j))
       additionalDataInListB.add(listB.get(j))
}

Просто повторите это с противоположными значениями, чтобы заполнить объект additionalDataInListA. Это должно помочь :)

РЕДАКТИРОВАТЬ: это будет работать, только если это один и тот же объект. Это может быть не так. Если это не так, вам следует сравнить одну из черт, вероятно, emp_id, чтобы увидеть, совпадают ли они. Если они не совпадают, добавьте другой в новый список.

person Jake Gascho    schedule 10.06.2013
comment
contains будет работать, только если вы переопределите equals в Employee - person Majid Laissi; 10.06.2013
comment
Это не сработает, если equals не был реализован с использованием только идентификатора сотрудника. - person Stijn Geukens; 10.06.2013
comment
это сработает, если у вас реализовано equals, но я думаю, что методы api предпочтительны - person tgkprog; 10.06.2013

class Employee {
    private int empId;
    ...
    @Override
    public int hashCode() { return empId; }

    @Override
    public boolean equals(Object other) {
        return other != null && other instanceof Employee && other.empId == empId;
    }
}

Вышеупомянутое позволит вам создать Set<Employee> employees = new HashSet<Employee>().

Наборы могут выполнять операции набора, такие как removeAll и сохранить все.

Это было бы оптимально (чего нельзя сказать о List).

person Joop Eggen    schedule 10.06.2013

Это очень просто: сначала переберите массив и получите сумму всех чисел. Поскольку мы знаем сумму натуральных чисел от 1 до n, мы можем записать как n * (n + 1) / 2. Теперь нам нужно вычесть сумму массива из [n * (n + 1) / 2].

Здесь мы получаем недостающий номер.

вы можете реализовать эту логику в своем коде, надеюсь, вы поняли мою мысль.

Источник с примером

person Himanshu Tewari    schedule 13.05.2015