Java基础总结十七(集合2)

                                                List接口

1.1     接口特点及主要子类

 单列集合

 可存放重复元素

 元素有序

 主要子类

ArrayList:底层数据结构是数组结构。线程不安全的。所以ArrayList的出现替代了Vector。增删慢,查找快。

LinkedList:底层是链表数据结构。线程不安全的,同时对元素的增删操作效率很高。

Vector:底层数据结构是数组结构。jdk1.0版本。线程安全的。无论增删还是查询都非常慢,已被ArrayList替代。

1.2     List接口常用方法

void add(int index, E element)                  //指定索引添加元素

E remove(int index)                                              //移除指定索引处元素

E get(int index)                                             //获取指定索引元素

E set(int index, E element)                         //修改指定索引元素

List<E> subList(int fromIndex, int toIndex)//截取指定索引子集

int indexOf(Object o)                                  //返回指定元素索引位置

ListIterator<E> listIterator()         注意:用于应对并发修改异常的返回迭代器方法与迭代器

1.1     具体子类介绍

1.1.1   ArrayList

ArrayList底层数据结构是数组结构。线程不安全的,所以运行速度快,ArrayList的出现替代了Vector。增删慢,查找快,由于日常开发中使用最多的功能为查询数据,遍历数据,所以ArrayList是最常用的集合。目前市面上许多程序员开发时并不严谨,非常随意地使用ArrayList完成任何需求,这种用法是不提倡的。

1.1.2   LinkedList

LinkedList与ArrayList不同,LinkedList是方便添加删除的List。实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,索引该具体子类的特点在于提供了大量首尾操作。

public void addFirst(E e)           添加首个元素

public void addLast(E e)           添加最后元素

public E getFirst()                       获取首个元素

public E getLast()                       获取最后元素

以及其替代方法

1.1.3   Vector

Vector:我们可以将其理解为版本旧的、安全的、效率低的ArrayList,Vector中提供了一个独特的取出方式,就是枚举Enumeration。此接口Enumeration的功能与 Iterator 接口的功能是类似的。

有兴趣的可以自己了解:

public E elementAt(int index)

public E firstElement()

public E lastElement()

public void setElementAt(E obj, int index)

public void removeElementAt(int index)及其他删除

public Enumeration<E> elements()

                                              Set接口

2.1     接口特点及主要子类

Set是不包含重复元素的集合接口,其子类均无法存放相同元素。

最常用的子类是无序不可重复的HashSet。其方法与Set接口方法相同。

HashSet下还有子类LinkedHashSet,可预测迭代顺序的Set集合。

2.2     判断元素唯一原理

2.2.1   ArrayList的contains方法判断元素是否重复原理

ArrayList的contains方法会使用调用方法时,传入的元素的equals方法依次与集合中的旧元素所比较,从而根据返回的布尔值判断是否有重复元素。此时,当ArrayList存放自定义类型时,由于自定义类型在未重写equals方法前,判断是否重复的依据是地址值,所以如果想根据内容判断是否重复,需要重写equals方法。

2.2.2   HashSet的add/contains等方法判断元素是否重复原理

Set集合不能存放重复元素,其添加方法在添加时会判断是否有重复元素,有重复不添加,没重复则添加。

HashSet集合由于是无序的,其判断唯一的依据是元素类型的hashCode与equals方法的返回结果。规则如下:

先判断新元素与集合内已经有的旧元素的HashCode值

如果不同,判断元素不同。

如果相同,再判断equals比较结果,返回true则相同,返回false则仍然不同。

所以,使用HashSet存储自定义类型,如果没有重写该类的hashCode与equals方法,则判断重复时,使用的地址值,如果想通过内容比较元素是否相同,需要重写该类的hashcode与equals方法。

hashCode方法重写规则:将该对象的各个属性值hashCode相加即是整个对象的HashCode值。如果是基本类型,类似int,则直接返回int值就是该属性的hash值,如果是引用类型,类似String,就调用该成员变量的hashCode方法返回该成员变量hash值。这样可以根据对象的内容返回hashCode值,从而可以根据hashCode判断元素是否唯一。

但是由于在一些”碰巧的”情况下,可能出现内容不同但hashCode相同的情况,为了避免这些情况,我们加入一些干扰系数。

可是加入干扰系数后,仍会出现一些”碰巧”的情况,所以我们还要进行equals的二次判断。

                                                     泛型

3.1     泛型概述

我们在集合中大量使用到了泛型,这里来完整地介绍泛型知识。

泛型用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数传递。

泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型。

泛型的定义:定义泛型类可以预支地使用未知的类型。

泛型的使用:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

3.2     泛型代码实现

泛型类:

                  定义:类名后<变量>  如:class A<E> {使用E完全类的定义}

                  使用:创建对象时确定类型

泛型方法:

                  定义:方法返回值前<变量> 如:public <T> void method(){使用T}

                  使用:调用方法时确定类型

泛型接口:

                  定义:接口后<变量> 如: interface B<T>{使用T完成接口定义}

                  使用:

1、定义类时确定类型

2、始终不确定类型,直到创建对象时确定类型

3.3     泛型优点及其他

3.3.1   泛型其他 

在JDK1.5出现前,使用Object代表任意类型,但在使用时,涉及到了强转的麻烦。泛型替代了Object来代表任意类型。

泛型在编译时会擦除:泛型仅用来在编译期限制、方便程序员的操作,实际上真正编译后的.class中是没有泛型的,其中仍然使用的为Obejct类,通过类似多态的方式完成任意某个类型的指定。

泛型通配符?

定义:(查看ArrayList的构造方法)无法在类中使用

            使用:调用方法时可以给予任意类型。参照Arraylist的构造方法

? extends E代表只要是E类型的子类即可

? super E代表只要是E类型的父类即可

3.3.2   泛型优点

提高程序的安全性

将运行期问题转移到了编译期

省去了类型强转的麻烦

优化了程序设计








猜你喜欢

转载自blog.csdn.net/m0_37044606/article/details/80742172