我们需要比较具有一些公共字段的不同对象的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.name
与Person.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
构造函数,它只需要Person
和PersonNpi
,并相应地获得所需的信息。
您应该详细说明,使用超类,并使用contains()
函数。换言之,通过一个函数,使Person
和PersonNpi
的比较更容易。
编辑:您的第二个问题在很大程度上取决于您对Employee
、Person
和PersonNpi
的进一步实施。现在,我将再次假设您有一些方法可以验证Employee
、Person
和PersonNpi
之间的相等性。
我建议不要在一个循环中进行检查,因为您有两个贯穿始终的ArrayLists
。对于第一个List
中的每个记录,都会运行PersonNpi
-列表。因此,可能发生的情况是,在我们检查了所有内容后,一些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);
此方法确实需要为所有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
,以便在迭代时从列表中删除。因此,在personList
和npiList
中,只剩下单打,因为我们将双打添加到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);
}
这样的东西应该可以工作。它假设您有一种从Person
和PersonNpi
构造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
检查该人员是否在哈希映射中。