java 如何替换java集合中的对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36726835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I replace object in java collection?
提问by norbi771
I am trying to replace element in collection with new modified version. Below is short code that aims to demonstrate what I'd like to achieve.
我正在尝试用新的修改版本替换集合中的元素。以下是旨在演示我想要实现的目标的简短代码。
The whole idea is that I have one object that consists of collections of other objects. At some point in time I am expecting that this objects in collections (in my example phones) might require some modifications and I'd like to modify the code in one place only.
整个想法是我有一个由其他对象的集合组成的对象。在某个时间点,我希望集合中的这个对象(在我的示例手机中)可能需要一些修改,我只想在一个地方修改代码。
I know that in order to update the object's attributes I can use setters while iterating through the collection as demonstrated below. But maybe there is better, more general way to achieve that.
我知道为了更新对象的属性,我可以在遍历集合时使用 setter,如下所示。但也许有更好、更通用的方法来实现这一目标。
public class Customer {
private int id;
private Collection<Phone> phoneCollection;
public Customer() {
phoneCollection = new ArrayList<>();
}
//getters and setters
}
and Phone class
和电话课
public class Phone {
private int id;
private String number;
private String name;
//getters and setters
}
and
和
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);
}
}
Is this possible to achieve what I want? I tried copy constructor idea and other methods I found searching the net but none of them was working like I would expect.
这有可能实现我想要的吗?我尝试了复制构造函数的想法和我在网上找到的其他方法,但没有一个像我期望的那样工作。
EDIT 1
编辑 1
After reading some comments I got an idea
在阅读了一些评论后,我有了一个想法
I added the following method to my Phone class
我在 Phone 类中添加了以下方法
public static void replace(Phone org, Phone dst){
org.setName(dst.getName());
org.setNumber(dst.getNumber());
}
and now my foreach part looks like that
现在我的 foreach 部分看起来像那样
for (Phone phone : col) {
if (phone.getId() == p.getId()) {
Phone.replace(phone, p);
}
}
And it does the job. Now if I change the Phone class attributes I only need to change that method. Do you think it is OK solving the issue that way?
它可以完成工作。现在,如果我更改 Phone 类属性,我只需要更改该方法。你认为这样解决问题好吗?
回答by Ted Hopp
You should not modify the collection while you're iterating through it; that's likely to earn you a ConcurrentModificationException
. You can scan the collection for the first object that matches your search criterion. Then you can exit the loop, remove the old object, and add the new one.
迭代时不应修改集合;这很可能会为您赢得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);
}
Alternatively, you could declare a more specific type of collection, such as a List
, that would allow you to work with indexes, which would make the replacement step much more efficient.
或者,您可以声明更具体的集合类型,例如 a List
,它允许您使用索引,这将使替换步骤更加高效。
If your phone IDs are unique to each phone, you should consider using a Map<Integer, Phone>
that maps each phone ID to the corresponding phone. (Alternatively, you could use some sort of third-party sparse array structure that doesn't involve boxing each ID into an Integer
.) Of course, if your IDs aren't unique, then you might want to modify the above to gather a secondary collection of all matching phones (and reconsider the logic of your existing code as well).
如果您的电话 ID 对于每部电话都是唯一的,您应该考虑使用Map<Integer, Phone>
将每个电话 ID 映射到相应电话的 。(或者,您可以使用某种不涉及将每个 ID 装箱到Integer
.所有匹配手机的集合(并重新考虑现有代码的逻辑)。
回答by Partha
You can also use a Set (HashSet), this is only when you don't want to do the way Mike suggested.
您也可以使用 Set (HashSet),这仅在您不想按照 Mike 建议的方式进行时使用。
Use the Phone as an item in the set. Don't forget to implement hashCode() and equals() in Phone. hashCode() should return the id, as it is supposed to be unique.
使用电话作为集合中的一个项目。不要忘记在Phone 中实现hashCode() 和equals()。hashCode() 应该返回 id,因为它应该是唯一的。
Since you are concerned about replacing the item, here's how HashSet will help you :
由于您担心替换项目,以下是 HashSet 将如何帮助您:
- Create an instance of your object.
- Remove the object you want to replace from the set.
- Add the new object (you created in step 1) back to the set.
- 创建对象的实例。
- 从集合中删除要替换的对象。
- 将新对象(您在步骤 1 中创建的)添加回集合。
Both these operations 2 & 3 are guaranteed in O(1) / constant time.
这两个操作 2 和 3 都保证在 O(1) / 常数时间内。
You don't need to maintain a map for this problem, that's redundant.
您不需要为此问题维护地图,这是多余的。
If you want to get the object from the collection itself and then modify it, then HashMap would be better, search is guaranteed in O(1) time.
如果你想从集合本身获取对象然后修改它,那么HashMap会更好,在O(1)时间内保证搜索。
回答by Mike M.
Instead of a list, use a mapwith the Phone's id as the key. Then your code looks like this:
使用以电话的 id 作为键的地图而不是列表。然后你的代码看起来像这样:
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);
}
回答by Maheswaran
If you take the object out from the collection and update its properties, it will get reflected in the same object in collection too.. Hence, you dont have to technically replace object after updating it. As "Mike M." pointed out, you can use hashmap to retrieve the object quickly without iteration and update the object values.
如果您从集合中取出对象并更新其属性,它也会反映在集合中的同一对象中。因此,您不必在更新后从技术上替换对象。作为“迈克M” 指出,您可以使用 hashmap 无需迭代即可快速检索对象并更新对象值。
回答by Zircon
If order matters to you, you can change Collection
to List
(Since you're always using an ArrayList
anyway) and then:
如果订单对您很重要,您可以更改Collection
为List
(因为您总是使用 an ArrayList
),然后:
int index = col.indexOf(phone);
col.remove(phone);
col.add(p, index);