两个ArrayLists的内部联接纯粹是用Java编写的

时间:2016-05-03 11:44:03

标签: java arraylist

有没有办法根据一个字段对两个不同对象的两个ArrayLists进行内连接?

让我说我得到了:

ArrayList<Car>
ArrayList<Owner>

Car将具有以下属性:Weight, Top speed, OwnerId

所有者将拥有以下属性:Name, Age, Id

结果将是ArrayList<Result>,其属性为:Weight, Top speed, Id, Name, Age

我想根据名为Id的单个字段建立这两个字段的内部联接。没有使用数据库或嵌套循环,有没有最佳方法呢?

6 个答案:

答案 0 :(得分:2)

假设你:

  • 使用Java 8
  • 您有List<Car> carsList<Owner> owners
  • Result有一个带有CarOwner
  • 的构造函数

这是List<Result>

的方法
final Map<Integer, Owner> ownersById = owners.stream()
   .collect(Collectors.toMap(k -> k.id, k -> k));
final List<Result> results = cars.stream()
   .map(car -> new Result(car, ownersById.get(car.OwnerId)))
   .collect(Collectors.toList());

其中:

  • 创建一个java.util.Map实例,其中键是所有者ID,值是所有者实例
  • 然后遍历汽车并创建Result个实例,其中包含对汽车和所有者的引用,使用之前创建的地图查找

答案 1 :(得分:1)

您想象它的方式是不可能的,尤其是ArrayList只能包含一种类型(或子类型/实现类)。但是,对于您来说,使用另一个通过其ID来映射对象的数据结构可能是一种解决方案。

HashMap<Integer, HashMap<Car, Owner>> map;

修改 HashMap中的Integer-type可用于存储id,它是汽车和所有者之间的连接。如果您执行以下操作:

map.get(10)

它将作为HashMap实例返回,包含一个汽车作为键,一个所有者作为相应值,两者都应具有id 10.但这不是隐含的,你必须通过创建Map来确保它。 / p>

此外,您可以编写一个“映射”内连接的类:

public class CarToOwner() {
     private Car car;
     private Owner owner;
}

修改 如果您有一个包含汽车和所有者的类,它会直接映射它们之间的关系。在创建CarToOwner类的实例时,您必须确保两种类型的id与它们之间的连接相同。

事实上,这不是属于某些目的的真正干净的解决方案。我只会将其用作在GUI中显示表格的“快速而肮脏”的方法。

修改 对于拥有多个车主或拥有多辆车的车主,有必要将属性存储在CarToOwner的列表中或创建多个CarToOwner实例。

答案 2 :(得分:1)

首先迭代List<Car>(您应该使用接口而不是实现)并在Map<Integer, Car>中添加每个元素。 (我认为ID是唯一的。)

然后迭代List<Owner>并将结果存储在List<Result>中。当然,你需要一个结构的构造函数来获取一个Car和一个所有者。

此处没有嵌套循环:)

答案 3 :(得分:1)

您可以使用Collection.retainAll()方法。

您必须以特殊方式(请参阅下面的代码)实现等于Car和Owner类中的方法。

例如,假设Car和Owner类都具有String id属性,则代码为:

public static void main(String[] args) {        
    ArrayList<Car> list1 = new ArrayList<Car>();
    list1.add(new Car("ID1"));
    list1.add(new Car("ID2"));
    list1.add(new Car("ID3"));


    ArrayList<Owner> list2 = new ArrayList<Owner>();
    list2.add(new Owner("ID1"));
    list2.add(new Owner("ID3"));
    list2.add(new Owner("ID4"));

    list1.retainAll(list2);
    System.out.println(list1);
}

static class Car
{
    public Car(String id)
    {
        super();
        this.id = id;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;

        if (obj instanceof Owner)
        {
            Owner other = (Owner) obj;
            if (id == null)
            {
                if (other.id != null)
                    return false;
            }
            else if (!id.equals(other.id))
                return false;
        }
        else if (obj instanceof Car)
        {
            Car other = (Car) obj;
            if (id == null)
            {
                if (other.id != null)
                    return false;
            }
            else if (!id.equals(other.id))
                return false;
        }
        return true;
    }

    @Override
    public String toString()
    {
        return "Car [id=" + id + "]";
    }

    public String id;
}

static class Owner
{
    public Owner(String id)
    {
        super();
        this.id = id;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (obj instanceof Owner)
        {
            Owner other = (Owner) obj;
            if (id == null)
            {
                if (other.id != null)
                    return false;
            }
            else if (!id.equals(other.id))
                return false;
        }
        else if (obj instanceof Car)
        {
            Car other = (Car) obj;
            if (id == null)
            {
                if (other.id != null)
                    return false;
            }
            else if (!id.equals(other.id))
                return false;
        }


        return true;
    }

    @Override
    public String toString()
    {
        return "Owner [id=" + id + "]";
    }

    public String id;
}

输出将是:

  

[Car [id = ID1],Car [id = ID3]]

显然在这种情况下你会有一个Car列表,​​如果你想要另一种类型,你可以确保两个类都继承自同一个超类,或者你可以确保两个类实现相同的接口而不是管理那个接口类型。

答案 4 :(得分:1)

假设Id的类型实现Comparable

首先,对列表进行排序,以便Id按升序排列:

Collections.sort(cars, new Comparator<Car>() {
  @Override public int compare(Car a, Car b) {
    return a.OwnerId.compareTo(b.OwnerId);
  }
});
Collections.sort(owners, new Comparator<Owner>() {
  @Override public int compare(Owner a, Owner b) {
    return a.Id.compareTo(b.Id);
  }
});

然后,遍历元素:

int ci = 0, oi = 0;
while (ci < cars.size() && oi < owners.size()) {

浏览cars列表,查找Id字段相同的连续块:

  Id idStart = cars.get(ci).OwnerId;
  int carStart = ci;
  while (ci < cars.size() && cars.get(ci).OwnerId.equals(idStart)) {
    ++ci;
  }
  List<Car> carsWithId = cars.subList(carStart, ci);

然后跳过具有较小Owner s的所有Id个实例:

  while (oi < owners.size() && owners.get(oi).Id.compareTo(idStart) < 0) {
    ++oi;
  }

然后找到与Owner具有相同Id的{​​{1}}个实例的块:

  int ownerStart = oi;
  while (oi < owners.size() && owners.get(oi).Id.equals(idStart)) {
    ++oi;
  }
  List<Owner> ownersWithId = owners.subList(ownerStart, oi);

最后,使用相同的ID对汽车/所有者对执行某些操作:

  for (Car car : carsWithId) {
    for (Owner owner : ownersWithId) {
      System.out.println(car + ", " + owner);
    }
  }
}

答案 5 :(得分:0)

如果你只想要两个数组的交集,你只需要在一个列表上循环,每当你在另一个列表中找到一个与当前循环元素具有匹配ID的元素时,将它放在第三个列表上(你想要持有交叉元素的那个)