在学习dom4j的时候,碰到了这样一个问题,使用Element的elements的方法获得了一个List<Element>集合,使用remove(int index)方法删除指定的元素后,将doucument写入后发现节点被删除了,但是在使用removeIf删除时,写入之后发现xml文件中的元素并没有被删除,下面时当时写的代码
remove(int index)方法
public void test5_1() throws IOException{
Element rootElement = document.getRootElement();
List<Element> elements = rootElement.elements();
List<Element> book = elements.get(1).elements();
book.remove(1);
write();//写入操作
}
removeIf(new Predicate<T>)方法
public void test5_1() throws IOException{
Element rootElement = document.getRootElement();
List<Element> elements = rootElement.elements();
List<Element> book = elements.get(1).elements();
book.removeIf(new Predicate<Element>() {
@Override
public boolean test(Element t) {
// TODO Auto-generated method stub
if(t.getName().equals("特价")){
return true;
}
return false;
}
});
write();
}
这就有点....
一开始以为使用book.removeIf(new Predicate<T>)只是删除了book集合中的数据,但并没有对document对象中的元素做更改导致的,但是为甚麽使用book.remove(int index)方法时却可以删除,这就有点说不通了
于是便开始翻看源代码,在查看list的实现类的时候发现有很多,当时不知道怎么想的,很自然的就选了ArrayList的实现,看了大半天,并没有什么收获,都只是将元素从list中集合删除。
再看list实现时突然想到,不同的实现类其中的remove方法和removeIf方法可能不一样,但是怎么知道book.remove(1)调用的是哪个实现类呢?查看dom4j的api后发现返回值elements方法的返回值也只是java.util.list并没有什么有价值的信息,如果打印它的类类型呢,果断试了以下book.getClass(),输入结果:
发现它的实现类是org.dom4j.tree.BackedList,问题似乎快要解决了,BackedList或许只是实现了list接口或是继承了它接口的实现类,并且只对remove方法做了可以删除元素的操作,但是并没有对removeIf方法做相关操作,为了验证推测,还得看下源码:
BackedList继承了ArrayList类:
接着看BackedList的remove方法:
super.remove(index)方法:
可以看出调用的是ArrayList中的remove方法,也就是先将指定的元素先从集合中删除
BackedList中remove的asNode方法
判断要删除的节点是否是Node类型的元素
BackedList中remove的removeNode方法:
最后将元素删除
接下来将是removeIf方法,但是在BackedList中并没有发现removeIf方法,那么按照继承关系它就会去它的父类中寻找removeIf方法,也就是ArrayList类中,这样的话就只能删除集合中的元素,而不是Doucment对象中的元素了,这也就解释了为什么remove方法可以删除Document中的元素,而removeIf方法不可以。