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

それらが拡張するスーパークラスが表示されないため、リストを手動で反復処理する必要があります。たとえば、属性にゲッターとセッターがあり、それPersonNpi.nameはほぼ同じであり、のようなPerson.firstname + Person.lastname関数があり、クラスにはsと比較するメソッドがあると想定しています。その場合、最初の配列をループし、2番目の配列に等しいものがあるかどうかすべての項目をチェックします。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ターがあり、それに応じて必要な情報を取得するという仮定も行いました。PersonPersonNpi

さらに詳しく説明し、スーパークラスを使用して、contains()関数を使用する必要があります。つまり、関数を使用してPersonとをPersonNpi簡単に比較できるようにします。

編集Employee:あなたの2番目の質問は、、、Personおよびのさらなる実装に極端に依存していなくても、非常に重要PersonNpiです。Employee今のところ、Personとの間の同等性を検証するいくつかのメソッドがあるともう一度仮定しますPersonNpi

実行されるループが2つあるため、1つのループでチェックを行わないことをお勧めしますArrayListsPersonNpi-listは、最初のすべてのレコードに対して実行されますList。したがって、すべてをチェックした後、いくつかは一致しないまま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>

1つのループで(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とでは、 -listにnpiListdoubleを追加して、他の2つのリストから即座に削除するため、singleのみが残ります。Employeeこのメソッドを使用して、2つのリストの残りのシングルを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を使用している場合は、次のようにすることができます(正しいjdkを使用して、btwをコンパイルして実行します):

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

このようなものが機能するはずです。これは、aと。Employeeからを構築する方法があることを前提としています。また、の構造はわからないので、アドレス照合ロジックの作成はお任せします。PersonPersonNpiAddress

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最初のリストを保存するために使用しますPersonNpiListmap.get(Person) == nullその人がハッシュマップに含まれているかどうかを確認するために使用します。

于 2012-12-04T16:06:26.483 に答える