本帖最后由 马文帅 于 2019-5-7 14:49 编辑
Java集合总结 Java集合是每个Java程序员在日常开发中都会使用到,而且有时候使用得好的话,能事半功倍。细数Java集合,其实比较常见的就是List、Set、Map和Queue,在这四者之中,除了Map之外,其他三个接口都继承于Collection。
在这里,首先我们要明确的是,List、Set、Map和Queue其实只是以接口的形式存在着的,所以在日常的程序开发中,请不要出现说想要直接初始化它们的想法和做法,虽然笔者也曾经犯过这样子的错误。
继承与Collection接口的–List接口List接口本身的特点 List接口在Java的集合类中充当的是一个元素有序、元素可重复的集合角色。List继承于Collection集合,故其拥有了Collection集合的全部方法,同时,List集合也拥有属于自己的方法:用来实现根据元素索引来操作集合元素的作用。通过List集合的源码(JDK1.7)我们简单地看看List集合包含的方法:[mw_shl_code=java,true]package java.util;
public interface List extends Collection {
int size(); //集合元素的数量
boolean contains(Object o); //是否包含某变量,包含返回ture
Iterator<E> iterator();
Object[] toArray(); //将集合转化为一个数组,所有的集合元素变成相应的数组元素
<T> T[] toArray(T[] a); //将集合转化为一个类型T数组
boolean add(E e); //增加元素,成功返回true
boolean remove(Object o); //移除元素,成功返回true
boolean containsAll(Collection<?> c); //是否包含集合c中的全部元素,若是返回true
boolean addAll(Collection<? extends E> c); //添加整个集合c中全部元素,
boolean addAll(int index, Collection<? extends E> c);
boolean removeAll(Collection<?> c); //移除该List集合中包含的c中的全部元素
boolean retainAll(Collection<?> c); //是否包含c集合中的元素,包含返回ture
void clear(); //清空集合
boolean equals(Object o);
int hashCode();
E get(int index); //根据index取元素值
E set(int index, E element); //根据index把List该元素重新复制element
void add(int index, E element); //根据index添加新元素element
E remove(int index);
int indexOf(Object o); //返回对象o在List集合中第一次出现的位置索引
int lastIndexOf(Object o); //返回对象o在List集合中最后一次出现的位置索引
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
List<E> subList(int fromIndex, int toIndex); //截断集合
}
常见的继承List接口的实用类- ArrayList
ArrayList是基于数组实现的List类,故其封装了一个动态的、允许再分配的Object[]数组,ArrayList用initialCapacity参数来设置该数组的长度,当长度超过预设值后,ArrayList会动态增加。
ArrayList类是线程不安全的,如果要保证该集合的同步性,必须在程序中手动保证。
值得注意的是:虽说与以链表形式建立的LinkedList相比,ArrayList()的插入和修改速度较慢,但那个也是建立在数据量较大的情况下的,在数据量较小的情况下,ArrayList()不一定比LinkedList()方法要慢。另外,ArrayList在末尾插入和删除数据的话,速度反而比LinkedList要快 - LinkedList
LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。
因为除了继承List接口外,LinkedList接口也继承了Deque接口,故也可以当作“栈”和队列(双向队列)来使用。因此LinkList接口也会多出一些Deque接口方面的方法,如offer()(将元素接到队列的尾部)、push()或offerFirst()(将元素加入栈的顶部)、peek()或peekFirst()(访问但是不删除栈顶元素)、pop()或者pollLast()(将栈顶元素弹出栈)等方法。 - Vector
Vector与ArrayList十分地相像,都是基于数组实现的List类,其也是封装了一个动态分配的Object[]数组,也可以使用initialCapacity参数来设置该数组的长度。
Vector是线程安全的,但是也因此Vector的性能很差。 - Stack
Stack是继承与Vector的子类,它主要用来模拟”栈“,因此也具备了peek()、pop()、push()等主要用于栈操作的方法。
由于Stack是一个比较古老的Java集合类,它同样是线程安全的,但也因此暴露出了性能较差的缺点,如果程序中要使用栈这样的数据结构的话,可以试一试ArrayDeque,该类也是List的实现类,但和LinkedList一样也继承了Deque接口。
继承与Collection接口的–Set接口Set接口本身的特点- Set代表的是无序的、不可重复的集合。因此在Set集合中加入数据元素时,Set集合通常不用记住元素的添加顺序。不可重复则是说当将两个相同的元素加入到一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被添加
常见的继承Set接口的实用类- HashSet
HashSet按照Hash算法来存储集合中的元素,因此具有良好的存取和查找功能。
HashSet有三个特点:与TreeSet不同,HashSet是无序的;不是线程同步;集合元素可以是null值。
HashSet集合的存储过程:当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该值决定该对象在HashSet中的存储位置。如果有两个元素通过equals()方法返回true,但他们的hashCode()方法返回值不相等,HashSet也会将其存储在不同的位置。也就是说:HashSet的添加元素判断标准是:两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。 - LinkedHashSet
LinkedHashSet是继承于HashSet的子类。
但是与父类不同的是,LinkedHashSet用以链表的形式来维护元素的次序,也就是说:LinkedHashSet是有序的。遍历该集合时输出顺序为添加顺序。 - TreeSet
TreeSet是SortedSet接口的实现类,所以TreeSet可以确保集合元素处于排序状态。TreeSet使用红黑树来维护集合元素的次序。如果实现comparator()方法,可以实现定制排序。如果采用自然排序,则返回null。
TreeSet集合的特有方法:first()、last()、lower(Object e)(返回指定元素之前的元素)、higher(Object e)(返回指定元素之后的元素)等等。
下面我们说一说TreeSet的定制排序和自然排序:
1、 定制排序
通过Comparator接口的帮助,实现降序排序。
2、 自然排序
TreeSet通过CompareTo(Object obj)比较元素之间的大小关系,将集合元素按升序排列。实现元素必须实现Comparable元素,而且在比较的时候如果出现不同类型时要转换类型后比较。 - EnumSet
EnumSet是专门为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。
EnumSet在内部以位向量的形式存储,十分紧凑、高效,因此EnumSet对象占用内存很小,且运行效率很高。但是该集合元素中不允许加入null元素。
|
|