Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java中的ArrayList上添加侦听器_Java_List_Arraylist_Listener_Add - Fatal编程技术网

如何在java中的ArrayList上添加侦听器

如何在java中的ArrayList上添加侦听器,java,list,arraylist,listener,add,Java,List,Arraylist,Listener,Add,我想用java创建自己的ArrayList实现,它可以在列表发生变化时监听,并在发生变化时执行操作。 从我所读到的,我明白我不能扩展ArrayList然后添加listener 我想在类中使用MyList作为带有public修饰符的变量,这样用户就可以直接更改它,并在更改它时执行操作 class MyList extends ArrayList<object>.... { ... } class UseOfMyList { public MyList places = new M

我想用java创建自己的ArrayList实现,它可以在列表发生变化时监听,并在发生变化时执行操作。 从我所读到的,我明白我不能扩展ArrayList然后添加listener

我想在类中使用MyList作为带有public修饰符的变量,这样用户就可以直接更改它,并在更改它时执行操作

class MyList extends ArrayList<object>.... {  ... }
 class UseOfMyList {
 public MyList places = new MyList<Object>();
 places.add("Buenos Aires");
 //and to be able to do that
 List cities = new ArrayList<Object>();
 cities.add("Belmopan");
 places = cities;
class MyList扩展了ArrayList。。。。{  ... }
类UseOfMyList{
公共MyList位置=新建MyList();
地点。添加(“布宜诺斯艾利斯”);
//并且能够做到这一点
List cities=new ArrayList();
城市。添加(“贝尔莫潘”);
地方=城市;

那么,如何创建以及何时添加、删除或传递另一个列表以列出要执行的操作呢?

扩展
ArrayList
,您将无法做到这一点,因为它没有内置的通知机制(而且,因为它已被声明为
final
,因此无法扩展)。但是,您可以通过创建自己的
List
实现,并针对
add()
remove()
方法添加“侦听器”功能来实现所需的结果:

class MyList<T>{
    private ArrayList<T> list;

    public MyList(){
        list = new ArrayList<>();
        ...
    }
    public void add(T t){
        list.add(t) 
        //do other things you want to do when items are added 
    }
    public T remove(T t){
        list.remove(t);
        //do other things you want to do when items are removed
    }
}
类MyList{
私有数组列表;
公共MyList(){
列表=新的ArrayList();
...
}
公共无效添加(T){
列表。添加(t)
//在添加项目时执行其他您想执行的操作
}
公共T移除(T){
列表。删除(t);
//在删除项目时执行其他您想执行的操作
}
}
响应)

私有类MyList扩展了ArrayList{
@凌驾
公共无效排序(比较器c){
超级排序(c);
resetLancamentos();//调用一些metod;)
}
//...
@凌驾
公共布尔removeAll(集合c){
//若要更改生成的方法体,请选择工具|模板。
布尔ret=super.removeAll(c);
resetLancamentos();//一些像fireObjChanged()这样的方法也可以完成这项工作
返回ret;
}
}
我知道这是个老问题。 对于任何格式错误或代码行丢失,我提前表示歉意。我是一个长期用户,第一次参与

无论如何,由于从JDK11中删除了JavaFX,我被迫编写了自己的ObservableList版本。当然,我们可以用JMods或Maven将JavaFX插入,但仅对FXCollections来说,这似乎有点过分了

长话短说……呃:)

我开始阅读这个老问题,但答案并不完全符合我的需要,所以我添加了一个自定义事件/侦听器类

我想我可以分享,因为这个网站把我的编码提高了10倍

public static void main(String[] args) {        
    BackedList<String> list = new BackedList();
    list.addListener(new BackedListListener<String>(){
        @Override
        public void setOnChanged(ListChangeEvent<String> event) {
            if (event.wasAdded()) {
                event.getChangeList().forEach(e->{
                   // do whatever you need to do                        
                    System.out.println("added: " + e);
                });
            }
            if (event.wasRemoved()) {

                // do whatever you need to dl
                event.getChangeList().forEach(e->{System.out.println(e + " was removed");});
            }
        }
    });
publicstaticvoidmain(字符串[]args){
BackedList=新的BackedList();
addListener(新的BackedListListener(){
@凌驾
public void setOnChanged(ListChangeEvent事件){
if(event.wasAdded()){
event.getChangeList().forEach(e->{
//做你需要做的事
系统输出打印项次(“添加:”+e);
});
}
if(event.wasRemoved()){
//做你需要做的一切
event.getChangeList().forEach(e->{System.out.println(e+“已删除”);});
}
}
});
类:BackedObservableList

    public class BackedObservableList<T> implements List<T> {
        private final List<T> backed;

    public BackedObservableList() {
        backed = new ArrayList();
    }

    public BackedObservableList(List<T> backed) {
        this.backed = backed;
    }

        /*

        You will want to override every method. For any method that performs an add/remove 
        operation, you will have to do some coding / testing. I'll do an add() op, a remove() 
        op, and an interator in this example. Anything that is not an add/remove op, you can straight up delegate it to the underlying list. 
Also remember that list.clear() is a removal operation, where you can simply iterate through the backed list and call the overide remove(T t) method, or just plop the whole backed list into the ListChangeEvent<T> class and delegate to the backed array again.


                */


     @Override
        public boolean add(T e) {
            if (backed.add(e)) {
                ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(e), backed.indexOf(e) + 1, true, e);
                    notifyListeners(event);
                return true;
                }
            return false;
                }

        }

    @Override
    public boolean remove(Object o) {
        if (backed.remove(o)) {
            ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(o), 

    backed.indexOf(o) + 1, false, o);
                notifyListeners(event);
                return true;
            }
            return false;
        }
    /*

    The iterator seemed easy enough, until I remembered the iterator.remove() call. 
    I still haven't fully tested it (it works, but only as far as I've used it)

    */
     @Override
        public Iterator<T> iterator() {        
            return new Iterator<T>() {
                T currentItem = null;
                int currentIndex = 0;

            @Override
            public boolean hasNext() {
                return backed.size() > currentIndex;
            }

            @Override
            public T next() {

                return currentItem = backed.get(currentIndex++);
            }

            @Override
            public void remove() {
                if (backed.remove(currentItem)) {
                    currentIndex--;
                    notifyListeners(new ListChangeEvent<T>(backed, currentIndex, currentIndex + 1, false, currentItem));
                }
            }
        };
    }


     private void notifyListeners(ListChangeEvent<T> event) {
            for (BackedListListener<T> listener : listeners) {
                listener.setOnChanged(event);
            }
        }

        private final List<BackedListListener> listeners = new ArrayList();

        public void addListener(BackedListListener<T> listener) {
            listeners.add(listener);
        }
公共类BackedObservableList实现列表{
私人最终名单;
公共备份可观察列表(){
backed=newarraylist();
}
公共备份可观察列表(列表备份){
this.backed=backed;
}
/*
您将要覆盖每个方法。对于任何执行添加/删除操作的方法
操作时,您必须进行一些编码/测试
任何不是添加/删除操作的操作,都可以直接将其委托给基础列表。
还要记住list.clear()是一个删除操作,您可以简单地遍历备份列表并调用overide remove(T)方法,或者将整个备份列表放到ListChangeEvent类中,然后再次委托给备份数组。
*/
@凌驾
公共布尔加法(TE){
如果(后面加上(e)){
ListChangeEvent事件=新的ListChangeEvent(this,backed.indexOf(e),backed.indexOf(e)+1,true,e);
通知侦听器(事件);
返回true;
}
返回false;
}
}
@凌驾
公共布尔删除(对象o){
如果(向后,移除(o)){
ListChangeEvent事件=新的ListChangeEvent(此,backed.indexOf(o),
指数(o)+1,假,o);
通知侦听器(事件);
返回true;
}
返回false;
}
/*
迭代器似乎很简单,直到我想起迭代器.remove()调用。
我还没有完全测试它(它可以工作,但仅限于我使用过的范围)
*/
@凌驾
公共迭代器迭代器(){
返回新的迭代器(){
T currentItem=null;
int currentIndex=0;
@凌驾
公共布尔hasNext(){
返回backed.size()>currentIndex;
}
@凌驾
公共交通工具{
return currentItem=backed.get(currentIndex++);
}
@凌驾
公共空间删除(){
如果(已备份。删除(当前项)){
当前索引--;
notifyListeners(新ListChangeEvent(backed、currentIndex、currentIndex+1、false、currentItem));
}
}
};
}
私有void notifyListeners(ListChangeEvent事件){
支持
    public class BackedObservableList<T> implements List<T> {
        private final List<T> backed;

    public BackedObservableList() {
        backed = new ArrayList();
    }

    public BackedObservableList(List<T> backed) {
        this.backed = backed;
    }

        /*

        You will want to override every method. For any method that performs an add/remove 
        operation, you will have to do some coding / testing. I'll do an add() op, a remove() 
        op, and an interator in this example. Anything that is not an add/remove op, you can straight up delegate it to the underlying list. 
Also remember that list.clear() is a removal operation, where you can simply iterate through the backed list and call the overide remove(T t) method, or just plop the whole backed list into the ListChangeEvent<T> class and delegate to the backed array again.


                */


     @Override
        public boolean add(T e) {
            if (backed.add(e)) {
                ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(e), backed.indexOf(e) + 1, true, e);
                    notifyListeners(event);
                return true;
                }
            return false;
                }

        }

    @Override
    public boolean remove(Object o) {
        if (backed.remove(o)) {
            ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(o), 

    backed.indexOf(o) + 1, false, o);
                notifyListeners(event);
                return true;
            }
            return false;
        }
    /*

    The iterator seemed easy enough, until I remembered the iterator.remove() call. 
    I still haven't fully tested it (it works, but only as far as I've used it)

    */
     @Override
        public Iterator<T> iterator() {        
            return new Iterator<T>() {
                T currentItem = null;
                int currentIndex = 0;

            @Override
            public boolean hasNext() {
                return backed.size() > currentIndex;
            }

            @Override
            public T next() {

                return currentItem = backed.get(currentIndex++);
            }

            @Override
            public void remove() {
                if (backed.remove(currentItem)) {
                    currentIndex--;
                    notifyListeners(new ListChangeEvent<T>(backed, currentIndex, currentIndex + 1, false, currentItem));
                }
            }
        };
    }


     private void notifyListeners(ListChangeEvent<T> event) {
            for (BackedListListener<T> listener : listeners) {
                listener.setOnChanged(event);
            }
        }

        private final List<BackedListListener> listeners = new ArrayList();

        public void addListener(BackedListListener<T> listener) {
            listeners.add(listener);
        }
public class ListChangeEvent<T> {
private final List<T> source;
private final List<T> changeList;
private final boolean wasAdded;    
private final int to, from;

public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, T... changeItems) {
    this(source, from, to, wasAdded, Arrays.asList(changeItems));
}


    public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, List<T> changeItems) {
        this.source = source;
        this.changeList = changeItems;
        this.wasAdded = wasAdded;
        this.to = to;
        this.from = from;                
    }

    public int getFrom() {
        return from;
    }

    public int getTo() {
        return to;
    }

    public List<T> getSource() {
        return source;
    }

    public List<T> getChangeList() {
        return changeList;
    }

    public boolean wasAdded() {
        return wasAdded;
    }

    public boolean wasRemoved() {
        return !wasAdded;
    }            
}
    /*
    Finally a little functional interface... or, because I was too lazy to change it to one, a simple one-liner abstract class with some generics
    */
    public abstract class BackedListListener<T> {

    public abstract void setOnChanged(ListChangeEvent<T> event);        

}