1

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

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 & address in the PersonNpi object in the PersonNpiList match to a Person object in the PersonList,如果是,则保存Person details + Npi to a new Arraylist<Employee>

希望我对这个问题很清楚。请让我知道如何有效地解决这个问题。

谢谢

哈利

编辑:

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

4

4 回答 4

4

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

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只需要Person和的构造函数PersonNpi,并相应地获取所需的信息。

您应该详细说明,使用超类并使用该contains()函数。换句话说,通过一个函数使比较Person和更容易。PersonNpi

编辑:您的第二个问题非常重要,如果不是非常依赖于您对Employee,PersonPersonNpi. 现在,我再次假设您有一些方法可以验证Employee,PersonPersonNpi.

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

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

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);

equals(Object)此方法确实需要您为所有 3 个人类实现该方法,您可以考虑将其放在像Human. 在这种情况下,您可以Object ArrayListArrayList<Human>

一个循环(需要equals(Object)3 个人类的方法)

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遍历两个列表,使我们能够在迭代时从列表中删除。所以在personList和 中npiList,只剩下单打,因为我们将双打添加到Employee-list 中,立即将它们从其他两个列表中删除。我们使用该方法将两个列表中剩余的单曲添加到我们的nonMatchedPerson-list 中addAll

Edit2:如果您出于某种原因无法编辑这些类,请制作 3 个包装类,例如:

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 (person.equals(personNpi)) {

对此:

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

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

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

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

于 2012-12-04T16:04:47.423 回答
2

如果您实现 equals 来比较有问题的值,则可以使用contains来查看对象是否在其他列表中。

否则,您将不得不手动遍历列表,并检查每个对象。

如果你使用 jdk8 Lambda,你可以做这样的事情(编译并运行 btw,使用正确的 jdk):

public static void main(String args[]) throws ParseException {
        TransformService transformService = (inputs1, inputs2) -> {
            Collection<String> results = new ArrayList<>();
            for (String str : inputs1) {
                if (inputs2.contains(str)) {
                    results.add(str);
                }
            }
            return results;
        };
        Collection<String> inputs1 = new ArrayList<String>(3) {{
            add("lemon");
            add("cheese");
            add("orange");
        }};
        Collection<String> inputs2 = new
                ArrayList<String>(3) {{
                    add("apple");
                    add("random");
                    add("cheese");
                }};
        Collection<String> results = transformService.transform(inputs1, inputs2);
        for (String result : results) {
            System.out.println(result);
        }
    }

    public interface TransformService {
        Collection<String> transform(Collection<String> inputs1, Collection<String> inputs2);
    }
于 2012-12-04T15:44:07.157 回答
2

像这样的东西应该工作。它假定您有一种Employee从 aPerson和 a构造 a 的方法PersonNpi。另外,由于您不告诉 a 的结构Address,我将留给您编写地址匹配逻辑。

public List<Employee> findCommonElements(List<Person> list1,
                                         List<PersonNpi> list2)
{
    List<Employee> common = new ArrayList<Employee>();
    for (Person p1 : list1) {
        PersonNpi p2 = find(list2, p1);
        if (p2 != null) {
            common.add(new Employee(p1, p2));
        }
    }
}

private PersonNpi find(List<PersonNpi> list, Person p) {
    for (PersonNpi p2 : list) {
        if (matches(p, p2)) {
            return p2;
        }
    }
    return null;
}

private boolean matches(Person p1, PersonNpi p2) {
    return /* logic for comparing name and address info */;
}

这是一个 O(n 2 ) 操作。您可以通过按名称和地址对两个数组进行排序来大大加快速度。排序操作是 O(n log(n)),然后可以将比较实现为 O(n) 操作。

于 2012-12-04T16:01:59.230 回答
-2

用于HashMap存储第一个列表PersonNpiList。用于map.get(Person) == null检查人是否在哈希图中。

于 2012-12-04T16:06:26.483 回答