java 如何在java中的ArrayList上添加监听器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16529273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add listener on ArrayList in java
提问by Xelian
I want to create my own implementation of ArrayList in java, that can listen when the list is changing and to do action when this happens. From what I have read, I understand that I can't extend ArrayList and then add listener.
我想在 java 中创建我自己的 ArrayList 实现,它可以在列表更改时进行侦听,并在发生这种情况时执行操作。从我读过的内容来看,我明白我不能扩展 ArrayList 然后添加侦听器。
I want to use MyList in class as a variable with publicmodifier, so users can change it directly and to be done action when he changes it.
我想在类中使用 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;
So how to create and when do add,remove or pass another list to MyList an action to be performed?
那么如何创建以及何时添加、删除或将另一个列表传递给 MyList 一个要执行的操作?
回答by drew moore
You're not going to be able to do this by extending ArrayList
, as it has no built-in notification mechanism (and, further, because it is has been declared final
and thus cannot be extended). However, you can achieve your desired result by creating your own List
implementation and adding your "listener" functionality vis a vis the add()
and remove()
methods:
您将无法通过扩展来做到这一点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
}
}
回答by Benson99
Old question, I know. I apologize in advance for any bad formatting or missing lines of code. I'm a long-time user, first time contributor.
老问题,我知道。对于任何格式错误或缺少代码行,我提前道歉。我是一个长期用户,第一次贡献者。
Anyhow, because of the removal of JavaFX from the JDK11, I was forced to write my own version of the ObservableList. Sure, we can plop JavaFX in with JMods or Maven, but it seems like a bit of an overkill just for the FXCollections.
无论如何,由于从 JDK11 中删除了 JavaFX,我被迫编写了自己的 ObservableList 版本。当然,我们可以将 JavaFX 与 JMods 或 Maven 一起使用,但对于 FXCollections 来说似乎有点过头了。
Long Story made Short...er :)
长话短说……呃:)
I started out reading this old question and the answer didn't suit my needs fully, so I've added a custom event/listener class.
我开始阅读这个老问题,但答案并不完全符合我的需要,所以我添加了一个自定义事件/侦听器类。
Figured I could share since this site has improved my coding 10 fold.
我想我可以分享,因为这个网站将我的编码改进了 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");});
}
}
});
Class: BackedObservableList
类: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);
}
Class: ListChangeEvent
类:ListChangeEvent
It simply provides a reference to the backed list (which you may want to wrap with Collections.unmodifiableList()
它只是提供对支持列表的引用(您可能希望使用Collections.unmodifiableList()
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;
}
}
Class: BackedListListener
类:BackedListListener
/*
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);
}
回答by AzzArr
the resp. ;)
分别 ;)
private class MyList extends ArrayList<Objects> {
@Override
public void sort(Comparator c) {
super.sort(c);
resetLancamentos(); // call some metod ;)
}
//...
@Override
public boolean removeAll(Collection c) {
//To change body of generated methods, choose Tools | Templates.
boolean ret = super.removeAll(c);
resetLancamentos(); // some metod like fireObjChanged() will do the job too
return ret;
}
}