如何在java集合中替换对象?

时间:2016-04-19 18:41:00

标签: java collections iteration

我正在尝试用新的修改版本替换集合中的元素。下面是简短的代码,旨在展示我想要实现的目标。

整个想法是我有一个由其他对象的集合组成的对象。在某个时间点,我期待集合中的这些对象(在我的示例手机中)可能需要一些修改,我只想在一个地方修改代码。

我知道为了更新对象的属性,我可以在迭代整个集合时使用setter,如下所示。但也许有更好,更通用的方法来实现这一点。

public class Customer {
    private int id;
    private Collection<Phone> phoneCollection;
    public Customer() {
        phoneCollection = new ArrayList<>();
    }
//getters and setters    

}

和电话课

public class Phone {
    private int id;
    private String number;
    private String name;
//getters and setters    
}

public static void main(String[] args) {
        Customer c = new Customer();

        c.addPhone(new Phone(1, "12345", "aaa"));
        c.addPhone(new Phone(2, "34567", "bbb"));
        System.out.println(c);

        Phone p = new Phone(2, "9999999", "new name");

        Collection<Phone> col = c.getPhoneCollection();
        for (Phone phone : col) {
            if (phone.getId() == p.getId()) {
//             This is working fine
//                phone.setNumber(p.getNumber());
//                phone.setName(p.getName());

//              But I'd like to replace whole object if possible and this is not working, at least not that way
                  phone = p;
            }
        }
        System.out.println(c);
    }
}

这可能实现我想要的吗? 我尝试了复制构造函数的想法和我在网上搜索的其他方法,但没有一个像我期望的那样工作。

编辑1

在阅读了一些评论之后,我有了一个想法

我将以下方法添加到我的Phone类

public static void replace(Phone org, Phone dst){
    org.setName(dst.getName());
    org.setNumber(dst.getNumber());
}

现在我的foreach部分看起来像那样

    for (Phone phone : col) {
        if (phone.getId() == p.getId()) {
            Phone.replace(phone, p);
        }
    }

它完成了这项工作。 现在,如果我更改Phone类属性,我只需要更改该方法。你认为以这种方式解决问题是否合适?

5 个答案:

答案 0 :(得分:3)

在您重复使用该集合时,不应修改该集合;这可能会让你获得ConcurrentModificationException。您可以扫描集合中第一个符合搜索条件的对象。然后你可以退出循环,删除旧对象,然后添加新对象。

Collection<Phone> col = c.getPhoneCollection();
Phone original = null;
for (Phone phone : col) {
    if (phone.getId() == p.getId()) {
        original = phone;
        break;
    }
}
if (original != null) {
    Phone replacement = new Phone(original);
    replacement.setNumber(p.getNumber());
    replacement.setName(p.getName());
    col.remove(original);
    col.add(replacement);
}

或者,您可以声明一种更具体的集合类型,例如List,它允许您使用索引,这将使替换步骤更有效。

如果您的手机ID对每部手机都是唯一的,则应考虑使用Map<Integer, Phone>将每个手机ID映射到相应的手机。 (或者,您可以使用某种第三方稀疏数组结构,不会将每个ID装入Integer。)当然,如果您的ID不是唯一的,那么您可能会想修改上述内容以收集所有匹配手机的二级集合(并重新考虑现有代码的逻辑)。

答案 1 :(得分:1)

你也可以使用Set(HashSet),这只是在你不想做Mike建议的时候。

将手机用作套装中的项目。别忘了在Phone中实现hashCode()和equals()。 hashCode()应该返回id,因为它应该是唯一的。

由于您担心更换项目,所以HashSet将如何帮助您:

  1. 创建对象的实例。
  2. 从集中删除要替换的对象。
  3. 将新对象(您在步骤1中创建的)添加回集合。
  4. 这两项操作2&amp;在O(1)/恒定时间内保证3。

    您不需要为此问题维护地图,这是多余的。

    如果你想从集合本身获取对象然后修改它,那么HashMap会更好,在O(1)时间内保证搜索。

答案 2 :(得分:0)

使用带有电话ID的map代替列表。然后您的代码如下所示:

public static void main(String[] args) {
        Customer c = new Customer();

        c.addPhone(new Phone(1, "12345", "aaa"));
        c.addPhone(new Phone(2, "34567", "bbb"));
        System.out.println(c);

        Phone p = new Phone(2, "9999999", "new name");

        Map<Integer, Phone> phoneMap = c.getPhoneMap();
        phoneMap.put(p.getId(), p);

        System.out.println(c);
}

答案 3 :(得分:-1)

如果从集合中取出对象并更新其属性,它也会反映在集合中的同一个对象中。因此,您不必在更新后从技术上替换对象。 作为&#34; Mike M。&#34;指出,您可以使用hashmap快速检索对象而无需迭代并更新对象值。

答案 4 :(得分:-2)

如果订单对您很重要,您可以将Collection更改为List(因为您始终使用ArrayList),然后:

int index = col.indexOf(phone);
col.remove(phone);
col.add(p, index);