Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
156 views
in Technique[技术] by (71.8m points)

java - How to properly add a value change listener to Map.Entry?

A project im working on currently requires me to ensure that while looping through a map's entries, if Entry.setValue is called, it would trigger a value change event. I see I can try something like adding a listener into an extension of the Map class on the .put method. My question is, would entries being changed trigger a listener in the map's put method? Or would I be forced to extend the Map.Entry class and stick listener logic into its setValue method?

Apologies in advance if this question is dumb - im new to using Maps in this way and a lot of the information ive seen so far has only lead to extending the Map itself, which seems easiest but i dont know if it would cover my case.

question from:https://stackoverflow.com/questions/65942847/how-to-properly-add-a-value-change-listener-to-map-entry

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In a pinch you could use the PropertyChangeSupport class. It makes managing propertyChanges very easy. There's not much to tell here. The parties that want to listen for changes register their listener with the map. Then when the map modifies the value, the support fires off an event to all the listeners. The values that are returned in the Event class may be altered to ones chosing.

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.HashMap;

public class PropertyChangeDemo implements PropertyChangeListener {
    
    public static void main(String[] args) {
        // leave static context of main
        new PropertyChangeDemo().start();
    }
    public void start() {
        MyMap<String,Integer> map = new MyMap<>();
        map.addMapListener(this);
        map.put("B",20);
        map.put("B",99);
        map.put("A",44);
        
        map.entrySet().forEach(System.out::println);
    }

Prints

source = map
oldValue = null
newValue = 20
source = map
oldValue = 20
newValue = 99
source = map
oldValue = null
newValue = 44
A=44
B=99

A listener for demonstration.

    public void propertyChange(PropertyChangeEvent pce) {
        System.out.println("source = " + pce.getPropertyName());
        System.out.println("oldValue = " + pce.getOldValue());
        System.out.println("newValue = " + pce.getNewValue());
    }
    
}

The modified class

class MyMap<K,V> extends HashMap<K,V> {
        
    private PropertyChangeSupport ps = new PropertyChangeSupport(this);

    // method to add listener
    public void addMapListener(PropertyChangeListener pcl) {
        ps.addPropertyChangeListener(pcl);
    }
    
    @Override 
     public V put(K key, V value) {
        V ret = super.put(key,value);
        ps.firePropertyChange("map", ret, value);
        return ret;
    }
}   

Note: There may be issues that have been missed in this simple solution. Testing should be conducted before put into production use. For one, there are many different ways to set an Entry's value. This only does it when put is invoked, either by the user or indirectly by the map itself.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...