我有Set
个A
类型的元素。
如果我修改了Set中包含的元素(考虑到这个修改可能会改变任何a
的身份),我的代码会闻到吗?
答案 0 :(得分:3)
例如,一个问题是,如果您向集合添加A a
,然后以更改其哈希码的方式变更a
,set.contains(a)
将有可能返回false。
琐碎的例子:
public static void main(String[] args) {
Set<A> set = new HashSet<> ();
A a = new A(1);
set.add(a);
System.out.println(set.contains(a)); //true
a.i = 2;
System.out.println(set.contains(a)); //false
}
static class A {
int i;
public A(int i) { this.i = i; }
@Override public int hashCode() { return i; }
}
答案 1 :(得分:1)
由于您可以通过修改内部的可变元素来中断package de.poller.StorrageBox;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass implements KeyListener {
JFrame frame;
JPanel panel;
JPanel panel1;
JPanel panel2;
public static void main(String[] args) {
MainClass c=new MainClass();
}
public MainClass() {
frame=new JFrame("test");
frame.setSize(new Dimension(500, 500));
frame.addKeyListener(this);
panel=new JPanel(new CardLayout());
frame.add(panel);
panel1=new JPanel();
JButton butt1=new JButton("test1111");
panel1.add(butt1);
panel2=new JPanel();
JButton butt2=new JButton("test222");
panel2.add(butt2);
panel.add(panel1,"1");
panel.add(panel2,"2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.requestFocus();
}
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyChar()=='a') {
activate1();
}
if(arg0.getKeyChar()=='b') {
activate2();
}
}
private void activate2() {
CardLayout cl=(CardLayout)(panel.getLayout());
cl.show(panel, "2");
}
private void activate1() {
CardLayout cl=(CardLayout)(panel.getLayout());
cl.show(panel, "1");
}
public void keyReleased(KeyEvent arg0) {}
public void keyTyped(KeyEvent arg0) {}
}
,因此,immutable肯定是首选。
答案 2 :(得分:1)
大多数情况下,一个集合应该只包含不可变量。
来自the JavaDoc of the Set interface:
注意:如果将可变对象用作集合元素,必须非常小心。如果在对象是集合中的元素时以影响等于比较的方式更改对象的值,则不指定集合的行为。这种禁止的一个特例是,不允许集合将自己作为一个元素包含在内。
强调我的。
如果您能够在不影响equals()
的情况下修改元素,我会强烈重新考虑您的equals实现是否正确。
答案 3 :(得分:0)
它很可能闻起来,因为如果修改了一个也用于计算hashCode的字段,则Set
会中断。
因此,对Set
中元素的修改可能会导致Set
。
相反,对List
中元素的修改永远不会破坏该列表。
琐碎的例子(从assylias回答中采取和扩展)
public class Main {
public static void main(String[] args) {
Set<A> set = new HashSet<>();
List<A> list = new ArrayList<>();
A a = new A(1);
set.add(a);
list.add(a);
System.out.println(set.contains(a)); // true
System.out.println(list.contains(a)); // true
a.i = 2;
System.out.println(set.contains(a)); // false
System.out.println(list.contains(a)); // true
}
static class A {
int i;
public A(int i) {
this.i = i;
}
@Override
public int hashCode() {
return i;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof A)) {
return false;
}
A other = (A) obj;
if (i != other.i) {
return false;
}
return true;
}
}
}