【问题标题】:IdentitySet / IdentityHashSet (use IdentityHashMap)IdentitySet / IdentityHashSet(使用 IdentityHashMap)
【发布时间】:2018-06-13 11:04:16
【问题描述】:

我知道IdentityHashMap,但我需要使用"IdentitySet" 之类的东西(将equals 用作o1 == o2)。我打算用一个“extractor”(JavaFX)来监听 Observable 列表:

 List<Person> deleteList = new ArrayList<>();
 List<Person> addList = new ArrayList<>();

 ObservableList<Person> list = FXCollections.observableArrayList(Person.extractor());
    list.add(new Person("a",1));
    list.add(new Person("b",2));
    list.add(new Person("c",3));

    list.addListener((ListChangeListener<Person>) observable -> {
        if(observable.next()) {
            if (observable.wasAdded()) {
                addList.addAll(observable.getAddedSubList());
            }
            if (observable.wasUpdated()) {
                deleteList.add(list.get(observable.getFrom()));
            }
            if (observable.wasRemoved()) {
                deleteList.addAll(observable.getRemoved());
            }
        }
    });

人物类:

public class Person {
private final StringProperty s;
private final DoubleProperty d;

//Getters and Setters
// ...

@Override
public int hashCode() {
    int result = s != null ? s.getValue().hashCode() : 0;
    result = 21 * result + (d != null ? Double.hashCode(d.getValue()) : 0);
    return result;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Person person = (Person) o;
    if (!s.getValue().equals(person.s.getValue())) return false;
    return d.getValue().equals(person.d.getValue());
}


/**
 *Extractor to observe changes in "Property" fields.
 * @return extractor
 */
public static Callback<Person, Observable[]> extractor() {
    return (Person p) -> new Observable[]{p.sProperty(), p.dProperty()};
}

我需要覆盖 equalshashCode 来解决我的其他问题。

Person p = new Person("a",1);
Set<Object> persons = new HashSet<>();
persons.add(p);
p.setD(999);
persons.add(p);
System.out.println(persons.size());  // size = 2;

persons.remove(p);
System.out.println(persons.size());  // size = 1;

【问题讨论】:

  • 你想在你的 Set 中存储什么?如果您存储的类的对象不覆盖 equals(),则 HashSet 将执行与 IdentityHashSet 相同的操作,因为 equals() 的默认实现仅在两个对象相同时才返回 true。
  • 我必须重写。

标签: java set javafx-8 observable identity-map


【解决方案1】:

【讨论】:

  • Guava 自己建议在存在此类选项的情况下优先使用 Java 类。我认为Collections.newSetFromMap 是更好的选择。
  • thx -> Set&lt;Person&gt; set = Collections.newSetFromMap( new IdentityHashMap&lt;&gt;()); 干得漂亮!
  • @kozmo 随时self answer - 你会得到一些代表,也许还有一些赞成票;)。
  • @BoristheSpider Guava 反正就是使用那个方法,它只是一个门面。
  • @BoristheSpider Guavas 版本更易于阅读 (imo)。 Collections 版本也不难,但不太明显。 Guava 准确地说明了你得到了什么(一个身份集),你不必介意它是如何构建的。 Java 版本在这方面有点冗长。对于有经验的程序员来说,我当然不是问题,但代码可能不仅适用于有经验的程序员。
【解决方案2】:

根据地图制作一组

谢谢,@BoristheSpider

Collections.newSetFromMap(...),返回一个由指定映射支持的Set(在我的例子中是➡️IdentityHashMap):

// get IdentytitySet wich wrap IdentityHashMap
Set<Person> persons = Collections.newSetFromMap(new IdentityHashMap<>()) 

// test 
Person p  = new Person("a",1);
Person p2 = new Person("a",1);
persons.add(p);
persons.add(p2);
System.out.println(persons.toString());

标准输出(漂亮的印刷品):

[
  Person{
    s=StringProperty [value: a],
    d=DoubleProperty [value:1.0]
  }, 
  Person{
    s=StringProperty [value: a], 
    d=DoubleProperty [value: 1.0]
  }
]
p.setD(999);
persons.add(p);
System.out.println(persons.toString());

标准输出(漂亮的印刷品):

[
  Person{
    s=StringProperty [value: a],
    d=DoubleProperty [value: 999.0]
  }, 
  Person{
    s=StringProperty [value: a], 
    d=DoubleProperty [value: 1.0]
  }
]
persons.remove(p)
System.out.println(persons.toString());

标准输出(漂亮的印刷品):

[
  Person{
    s=StringProperty [value: a], 
    d=DoubleProperty [value: 1.0]
  }
]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-23
    • 2014-05-19
    • 2015-06-17
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 2021-05-18
    相关资源
    最近更新 更多