【问题标题】:Java: implementation of notification provider vs. hashCode-driven MapJava:通知提供者与 hashCode 驱动的 Map 的实现
【发布时间】:2009-11-10 18:03:57
【问题描述】:

我已经为一组通用侦听器E 实现了抽象通用提供程序,后代必须用特定的通知代码覆盖notifyListener(E)。对于听众的后备名单,我选择WeakHashMap<K,V>。侦听器必须作为弱引用:

abstract public class NotificationProvider<E> {

    private Map<E, Object> listeners = new WeakHashMap<E, Object>();

    public addListener(E listener) {
        listeners.put(listener, null);
    }

    public void notifyListeners() {
        for (E listener: listeners.keySet())
            notifyListener(listener);
    }

    abstract protected void notifyListener(E listener);
}

典型用途:

    NotificationProvider<MyListener> provider;
    provider = new NotificationProvider<MyListener>() {
        @Override
        protected void notifyListener(MyListener listener) {
            listener.myNotification();
        }
    }
    provider.addListener(myListener1);
    provider.addListener(myListener2);
    provider.notifyListeners();

一切正常,但是当我需要AbstractList 后代类作为侦听器时,支持WeakHashMap 只接受一个侦听器实例!很明显 - 侦听器上的方法 hashCode()equals() 为所有实例(空列表)返回相同的值,因此 WeakHashMap.put 仅替换之前添加的侦听器。

    public class MyList extends AbstractList<MyItem> {
        // some implementation
    }
    NotificationProvider<MyList> provider;
    provider = new NotificationProvider<MyList>() {
        @Override
        protected void notifyListener(MyList listener) {
            // some implementation
        }
    }
    MyList list1 = new MyList();
    MyList list2 = new MyList();
    provider.addListener(list1);
    provider.addListener(list2); 
    provider.notifyListeners();  // only list2 instance is notified

什么是最好的解决方案?

  1. 使用另一个非 hashCode 支持集合——但 WeakHashMap 对我来说太棒了,因为自动为我管理弱引用

  2. 使用非泛型监听器,例如具有简单equals() { return (this == object); } 实现的抽象类——但这不是那么灵活

  3. 使用简单的 equals() 为侦听器使用一些包装器——但由于弱引用,此包装器不能对 addListener(E) 调用者透明

其他想法?

【问题讨论】:

  • 为了确保我理解问题:您是否尝试将 AbstractList 传递给您的 addListener() ?
  • 不,我有 AbstractList 的后代(实际上是 AbstractListDecorator 的后代),它实现了一些特定的接口,这个接口是监听器类。

标签: java equals listener hashcode weak-references


【解决方案1】:

WeakHashMap 有点坏了。它使用弱密钥,但不使用身份哈希。除非您的密钥类型的equals()hashCode() 使用“身份”,否则您不应使用WeakHashMap。相反,您需要 WeakHashMapIdentityHashMap 的组合。

一种可能性是使用来自 Google 收藏集的MapMaker。如果密钥很弱或很软,它会自动对密钥使用身份哈希/相等性。例如:

ConcurrentMap<K, V> myMap = new MapMaker().weakKeys().makeMap();

【讨论】:

【解决方案2】:

问题的症结似乎在于您的侦听器实现是子类化AbstractList,而不是覆盖equals() / hashCode()。我强烈建议不要使用这种类型的继承(实现继承),因为它违反了 OO 原则(多态可替换性原则)。

最好实现一个自定义侦听器类,该类可能引用AbstractList(如果需要),并且还提供自己的equals()hashCode() 实现。

【讨论】:

  • 在我的情况下,从 AbstractList 继承的原始 equals()hashCode() 实现很有用。将 MyList 用作侦听器只是次要用途。我想要的是 NotificationProvider 的防弹实现。但同意 equals()hashCode() 在所有项目中的使用必须相同...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 2010-10-19
  • 2011-08-18
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
相关资源
最近更新 更多