Java基础知识拾遗—集合篇之List

Java基础知识拾遗——集合篇之List

一、关于ArrayList和LinkList中contain()和remove()方法的底层调用

contain():判断集合中是否包含某元素
remove():如果集合中包含某元素,则移除该元素

可以知道,这两个方法都对集合中的元素进行了包含判断,那么在集合的内部对元素是如何进行判断的呢?通过查看源码我们知道,其实在调用contian()和remove()方法的时候,其实集合的内部都调用了元素对象的equals()方法,通过equals()方法返回的值来判断集合中是否包含该元素。如果在不重写equals()方法的前提下,该equals()方法比较的是对象元素的hash值,如果用户需要自定义比较元素对象,那么就只需要重写该对象的equals()方法就可以了。

对于set集合,首先set集合中的元素是唯一的,不重复的,那么在内部,set集合是如何保证集合中元素的唯一性的。同样,查看源码,发现set的内部是通过hashCode值和equals两个方法来共同保证元素的唯一性的。如果元素的hashCode值一样,则判断元素的equals方法,如果元素的hashCode值不同,那么就不判断equals方法,如果两个值完全一样,则判断 这两个元素为相同的元素
总结:Arraylist和LinkedList在判断元素是否相同的时候,是根据equals方法来判断的。set在判断元素是否相同的时候是通过hashCode和equals两者来判断的,而hashCode的判断优先级要大于equals的判断优先级

二、实时的删除集合中的某一个元素

在实际的研发过程中,我们会遇到这样的需求,就是在一个集合中,我需要剔除某一个元素,通常都会将集合中的元素与指定需要剔除的元素进行比较,如果一样,则remove掉。但是在实际操作过程中,会出现报ConcurrentModificationException的错误。那是因为集合内部在对集合进行操作的时候,都会对一个modCount的值进行判断,一旦集合进行了remove操作,那么这个modCount的值就会改变,当集合在检查这个modCount的时候发现值不同,这个时候就会抛出一个ConcurrentModificationException异常。所以我以前的做法是,重新创建一个集合B,然后遍历原始集合,一个个的将原始集合中的元素添加到新创建的集合B中,如果遇到指定的需要剔除的元素,则过滤掉,在后来的使用中,则使用新创建的集合B。

这样做的话很简单,也很好理解,但是会显得很不专业,如果给别人看到你写的这个代码,会显得自己很low,反正我当时是这样认为的,所以我在知道这个后,立马将我以前的代码改了过来。那这个方法就是使用迭代器Iterator,在Iterator中也有相应的remove方法,这个方法就是专门用来删除掉集合的元素的,调用这个方法并不会改变集合的modCount值,所以不会抛出以上所说的集合异常。

三、关于TreeSet内部比较的源码分析

set集合分为TreeSet和HashSet,其中hashSet中的元素是无序不可重复的,treeSet中的集合是有序且不可重复的

这里对treeSet中的元素是如何进行比较的进行重点说明:

首先,treeSet中的元素的数据结构是采用的二叉树的数据结构。那么treeSet中的元素是如何实现可比较性的呢?

1、首先就得保证treeSet中的元素实现Comparable接口,然后重写Comparable接口的compareTo方法,来自己定义元素的比较方法,

2、treeSet提供 一个包含比较器Comparator的构造方法,通过传入一个自己自定义的构造器来实现元素的可比较性,在定义Comparator的时候,需要重写该比较器中的compare方法,这样就实现了treeSet中元素的可比较性

在优先级上来说,如果treeSet既自定义了一个自己的比较器,元素类也实现了自己的Comparable接口,那么treeSet会优先选择构造器传入的构造器。也就是说,构造器传入的比较器优先级 > 元素自己实现的比较方法。

猜你喜欢

转载自blog.csdn.net/u014697083/article/details/80934498