比较不同对象的 2 个 Java 数组列表并将匹配的行添加到新列表

2022-01-25 00:00:00 compare match arraylist java

我们需要比较 2 个具有一些共同字段的不同对象的数组列表,然后将匹配的行存储到一个新的数组列表中.我已经寻找解决方案,但无法得到我需要的东西.

We need to compare 2 arraylists of different objects having some common fields, and then store the matching rows to a new arraylist. I have searched for solutions, but wasn't able to get what I need.

List<Person> personList = new ArrayList<Person>();
Person:
private String firstName;
    private String lastName;
    private String street1;
    private String street2;
    private String city;
    private String stateCode;
    private String zipCode;

List<PersonNpi> npiList = new ArrayList<PersonNpi>();
PersonNpi:
private String name;
    private String npi;
    private Address address;

所以我需要检查 name &PersonNpiList 中 PersonNpi 对象中的地址与 PersonList 中的 Person 对象匹配,如果是,则将 Person details + Npi 保存到新的 Arraylist

So I need to check if the name & address in the PersonNpi object in the PersonNpiList match to a Person object in the PersonList, and if yes save the Person details + Npi to a new Arraylist<Employee>

希望我对这个问题很清楚.请告诉我如何有效地解决这个问题.

Hope I'm clear on the question. Please let me know on how to solve this efficiently.

谢谢

哈利

我需要将不匹配的行(在第一个数组列表上)保存到另一个列表中.我需要另一个循环还是可以在同一个 For 循环上执行?请问有人吗?

推荐答案

由于我没有看到它们扩展的任何超类,因此您必须手动遍历您的列表.我假设很多,例如,您的属性有 getter 和 setter, PersonNpi.name 或多或少与 Person.firstname + Person.lastname 相同,您在 Address 中有一些功能,例如 boolean checkEquality(String street1, String street2, String city, String state, String zip),您的 Person 类有一个 getName() 方法来与 PersonNpis 进行比较.在这种情况下,循环遍历第一个数组,并检查第二个数组中的每个元素是否与它相等.

Since I don't see any superclasses from which they extend, you have to manually iterate through your lists. I am assuming a lot, for instance that you have getters and setters for your attributes, that PersonNpi.name is more or less the same as Person.firstname + Person.lastname, that you have some function in Address like boolean checkEquality(String street1, String street2, String city, String state, String zip), that your Person class has a getName() method to compare with PersonNpis. In that case, loop through the first array, and check for every item if the second has anything equal to it.

ArrayList<Employee> employees = new ArrayList<Employee>();
for(Person person : personList) {
  for(PersonNpi personNpi : npiList) {
    if (person.getName().equals(personNpi.getName()) && 
        person.getAddress().checkEquality(...address parts here...)) {
      employees.add(new Employee(person, personNpi));
    }
  }
}

再一次,我做了很多假设,你也有一个 Employee 构造函数,它只需要 PersonPersonNpi,并相应地获取所需的信息.

Again, I made a lot of assumptions, also the one that you have an Employee constructor which just requires the Person and the PersonNpi, and gets the required information accordingly.

您应该详细说明,使用超类,并使用 contains() 函数.换句话说,通过函数比较PersonPersonNpi更容易.

You should elaborate more, use superclasses, and use the contains() function. In other words, make comparing the Person and the PersonNpi easier through a function.

Edit:您的第二个问题非常依赖于您对 EmployeePersonPersonNpi.现在,我再次假设您有一些方法可以验证 EmployeePersonPersonNpi 之间的相等性.

Edit: your second question is highly, if not extremely dependant on your further implementation of Employee, Person and PersonNpi. For now, I'll yet again assume you have some methods that verify equality between Employee, Person and PersonNpi.

我建议不要在一个循环中进行检查,因为您有两个运行通过的 ArrayLists.PersonNpi-list 会针对第一个 List 中的每条记录运行.所以可能发生的情况是,在我们检查完所有内容后,一些 Persons 未匹配,而一些 PersonNpis 未匹配,因为我们没有标记哪个 PersonsPersonNpis 我们已经匹配.

I'd suggest to not do the checking in one loop, since you have two ArrayLists which are ran through. The PersonNpi-list is ran through for every record in the first List. So what might happen is after we checked everything, a few Persons are left unmatched, and a few PersonNpis are left unmatched, since we don't flag which Persons and PersonNpis we've matched.

总结:为方便起见,只需添加这部分:

In conclusion: for easiness' sake, just add this part:

ArrayList<Object> nonMatchedPersons = new ArrayList<Object>();
for (Person person : personList) 
    if (!employees.contains(person))
        nonMatchedPersons.add(person);
for (PersonNpi personNpi : npiList) 
    if (!employees.contains(personNpi))
        nonMatchedPersons.add(personNpi);

此方法确实需要您为所有 3 个人员类实现 equals(Object) 方法,您可以考虑将其放在像 Human 这样的超类之下.在这种情况下,您可以将 Object ArrayList 变成 ArrayList

This method does require you to implement the equals(Object) method for all 3 person classes, which you might consider putting beneath a superclass like Human. In that case, you can make the Object ArrayList into a ArrayList<Human>

只有一个循环(需要 equals(Object) 方法用于 3 个人类):

With one loop (requires equals(Object) method for the 3 person classes):

List<Employee> employees = new ArrayList<Employee>();
ArrayList<Object> nonMatchedPersons = new ArrayList<Object>();

Iterator<Person> personIterator = personList.iterator();
while (personIterator.hasNext()) {
    Iterator<PersonNpi> npiIterator = npiList.iterator();
    while(npiIterator.hasNext()) {
        Person person = personIterator.next();
        PersonNpi personNpi = npiIterator.next();
        if (person.equals(personNpi)) {
            employees.add(new Employee(person, personNpi));
            personIterator.remove();
            npiIterator.remove();
        }
    }
}

nonMatchedPersons.addAll(personList);
nonMatchedPersons.addAll(npiList);

解释:我们使用 Iterators 循环遍历两个列表,以使我们能够在迭代时从列表中删除.所以在 personListnpiList 中,只剩下单打,因为我们将双打添加到 Employee-list,立即将它们从另一个中删除两个列表.我们使用 addAll 方法将两个列表中剩余的单曲添加到我们的 nonMatchedPerson-list 中.

Explanation: we loop with Iterators through both lists, to enable us to remove from the list while iterating. So in the personList and the npiList, only the singles remain, as we add doubles to the Employee-list, instantly removing them from the other two lists. We add the remaining singles in the two lists to our nonMatchedPerson-list with the addAll method.

Edit2:如果您出于某种原因无法编辑这些类,请创建 3 个 wrapper 类,例如:

Edit2: If you can't edit those classes for whatever reason, make 3 wrapper classes, something like:

public class PersonWrapper {
    private Person person;

    public PersonWrapper(Person person) {
        this.person = person;
    }

    @override
    public boolean equals(Object other) {
        if (other == null) 
            return false;
        if (other instanceof PersonWrapper) {
            //etc etc, check for equality with other wrappers.
            ...
        }
    }
}

如果您选择使用这种方法,请在循环中更改此行:

If you choose to use this approach, change this line in the loop:

if (person.equals(personNpi)) {

到这里:

if (new PersonWrapper(person).equals(new PersonNpiWrapper(personNpi))) {

使用它,您仍然可以实现自己的 equals() 方法.

Using this, you can still implement your own equals() method.

另一种解决方案可能是您制作这样的静态方法:

Another solution could be that you make a static method like this:

public static boolean equals(Object this, Object that) {
    if (this instanceof Person || this instanceof PersonNpi) //et cetera, et cetera
        return true;
    return false;
}

现在只需调用 Person.equals(person, personNpi),假设您将方法放在类 Person 中.

Now just call Person.equals(person, personNpi), assuming you put the method in the class Person.

相关文章