在列表中迭代时将一个或多个匹配项分组

Group one or more matching items while iterating through in a list

如果我需要遍历列表并尝试将元素组合在一起,最好的方法是什么?

举例来说,我们有以下要循环的对象:

People
  |---Person
  |     -FirstName: Jimmy
  |     -LastName: Ward
  |     -Address1: 1 Main Street
  |     -Town: Yipee
  |     -Country: Canada
  |     -Postcode: ABC
  |---Person
  |     -FirstName: Johnny
  |     -LastName: Jones
  |     -Address1: 21 Jump Street
  |     -Town: SomeTownie
  |     -Country: Ireland
  |     -Postcode: ZZZ
  |---Person
  |     -FirstName: Vinny
  |     -LastName: McWhinney
  |     -Address1: 11 Blah Lane 
  |     -Town: Pastaville
  |     -Country: Italy
  |     -Postcode: ALO
  |---Person
  |     -FirstName: Tommy
  |     -LastName: Jones
  |     -Address1: 21 Jump Street
  |     -Town: SomeTownie
  |     -Country: Ireland
  |     -Postcode: ZZZ
  |---Person
  |     -FirstName: Wendy
  |     -LastName: Ward
  |     -Address1: 1 Main Street
  |     -Town: Yipee
  |     -Country: Canada
  |     -Postcode: ABC
  |---Person
  |     -FirstName: Jenny
  |     -LastName: Bloggs
  |     -Address1: 1 Yadda Road
  |     -Town: Blahdeblah
  |     -Country: Ireland
  |     -Postcode: XYZ

我需要遍历每个人,并创建一个具有相同地址和相同姓氏的人的群组。

例如,它从 Jimmy 开始,遍历列表以查找具有相同地址和姓氏的任何人,只有 Wendy 匹配,因此他们都被组合在一起。接下来是约翰尼,汤米是唯一的对手。

在遍历列表中的剩余人员时,我们不想对 Wendy 或 Tommy 执行相同的过程(因为他们已经分组)。所以我们需要从原始列表中删除那些已经匹配的,或者以某种方式插入到地图中?

我在想 while 循环,然后 for 循环来找到任何匹配项。免责声明:此提议的解决方案用于删除那些匹配项,因此可能偏离目标。

例如:

while (!originalPersonList.isEmpty()) {
  ArrayList<Person> newGroup = new ArrayList<Integer>();
  List<Integer> indexToRemove = new ArrayList<Integer>();
  newGroup.add(0);
  indexToRemove.add(0);
  for (int i=1; i < originalPersonList.size(); i++) {
    if (originalPersonList.get(0).Address1().equals( originalPersonList.get(i).Address1())
      && originalPersonList.get(0).Town().equals(originalPersonList.get(i).Town())
      && originalPersonList.get(0).Country().equals( originalPersonList.get(i).Country())
      && originalPersonList.get(0).Postcode().equals( originalPersonList.get(i).Postcode()
      && originalPersonList.get(0).Lastname().equals( originalPersonList.get(i).Lastname()) 
    {
       indexToRemove.add(i);
       newGroup.add(i);
    }
  }
  originalPersonList.removeAll(indexToRemove);
}

这是我的方向,但我觉得可能有更优雅的解决方案?

我只能使用 Java7。

我也尝试搜索类似的问题,但没有任何匹配的特定场景。

正如@HernánAlarcón 所说,Map 是一个很好的用例场景,可以满足您的要求。那么让我们一步步来吧:

创建人 POJO

public class Person {
    private String firstName;
    private String lastName;
    private String address;
    private String town;
    private String country;
    private String postCode;

//Constructor,Getters,Setters ommited for clarity
}

地图需要一个 class 作为具有适当 hashcode/equals 实现的键。因此,让我们创建一个包含您想要的条件的 class:

人物投影

public class PersonProjection {
    private String lastname;
    private String address;

    public PersonProjection(String lastname, String address) {
        this.lastname = lastname;
        this.address = address;
    }

    public String getLastname() {
        return lastname;
    }

    public String getAddress() {
        return address;
    }

    @Override
    public boolean equals(Object o) {

        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PersonProjection that = (PersonProjection) o;
        return Objects.equals(lastname, that.lastname) &&
                Objects.equals(address, that.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(lastname, address);
    }
}

下面是主要代码,如果没记错的话,它是 Java7 兼容的(8+ 使事情比这更简单):

public static void main(String[] args) {

    //Create map
    Map<PersonProjection, List<Person>> map = new HashMap<>();

    List<Person> personList = new ArrayList<>();

    //...Fill list

    for(Person p : personList)
    {
        //Create the projection
        PersonProjection projection = new PersonProjection(p.getLastName(),p.getAddress());

        //Initialize an arraylist whenever a new key is going to be inserted
        if(!map.containsKey(projection))
            map.put(projection,new ArrayList<Person>());

        //Put the person in the corresponding arraylist
        map.get(projection).add(p);
    }
}

请注意此代码未经测试。