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



我们需要比较具有一些公共字段的不同对象的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>

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

感谢

Harry

编辑:

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

由于我没有看到任何从中扩展的超类,因此您必须手动迭代列表。我假设了很多,例如,您的属性有getter和setter,PersonNpi.namePerson.firstname + Person.lastname大致相同,Address中有一些函数,如boolean checkEquality(String street1, String street2, String city, String state, String zip)Person类有一个getName()方法可以与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构造函数,它只需要PersonPersonNpi,并相应地获得所需的信息。

您应该详细说明,使用超类,并使用contains()函数。换言之,通过一个函数,使PersonPersonNpi的比较更容易。

编辑:您的第二个问题在很大程度上取决于您对EmployeePersonPersonNpi的进一步实施。现在,我将再次假设您有一些方法可以验证EmployeePersonPersonNpi之间的相等性。

我建议不要在一个循环中进行检查,因为您有两个贯穿始终的ArrayLists。对于第一个List中的每个记录,都会运行PersonNpi-列表。因此,可能发生的情况是,在我们检查了所有内容后,一些Persons不匹配,而一些PersonNpis不匹配,因为我们没有标记我们匹配的PersonsPersonNpis

结论:为了方便起见,只需添加此部分:

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<Human>

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

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-列表中,立即将它们从其他两个列表中删除。我们使用addAll方法将两个列表中的剩余单曲添加到我们的nonMatchedPerson-列表中。

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中。

如果您实现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);
}

这样的东西应该可以工作。它假设您有一种从PersonPersonNpi构造Employee的方法。此外,由于您没有说明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(n2)运算。通过按名称和地址对两个数组进行排序,可以大大加快速度。排序操作是O(n-log(n)),然后可以将比较实现为O(n)操作。

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

相关内容

  • 没有找到相关文章