集合框架1——List,Set

来源:互联网 发布:泡沫喷雾 知乎 编辑:程序博客网 时间:2024/06/08 07:05

数组 VS 集合

数组:长度固定;

集合:长度不固定

集合特点:

1.        用于存储对象

2.        集合长度可变

3.        可存储不同类型对象

集合继承关系


集合容器的创建及使用

步骤:

1.        导入文件 import java.util.*

2.        创建一个容器,使用Collection接口的子类 .ArrayList;

ArrayList  al = new ArrayList();

3.        加入对象

a1.add(“java1”);

常用方法:

增加元素:

 boolean

add(E e)
          确保此 collection 包含指定的元素(可选操作)。

 boolean

addAll(Collection<? extendsE> c)
          将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。

注:集合中存储的都是对象的引用。

删除元素:

 void

clear()
          移除此 collection 中的所有元素(可选操作)。

 boolean

remove(Object o)
   
       从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。

 boolean

removeAll(Collection<?> c)
         
 移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。

 

判断元素:

 boolean

equals(Object o)
          比较此 collection 与指定对象是否相等。

 boolean

contains(Object o)
          如果此 collection 包含指定的元素,则返回 true。

 boolean

containsAll(Collection<?> c)
          如果此 collection 包含指定 collection 中的所有元素,则返回 true。

boolean

isEmpty()
          
如果此 collection 不包含元素,则返回 true。

获取相关数据:

 int

size()
          返回此 collection 中的元素数。

 Object[]

toArray()
          
返回包含此 collection 中所有元素的数组。

<T> T[]

toArray(T[] a)
          
返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

Iterator<E>

iterator()
          返回在此 collection 的元素上进行迭代的迭代器。

 

获取两级和的交集

 boolean

retainAll(Collection<?> c)
          仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。

 

取出元素:


同过迭代器对数据进行取出。

it.next();在取完值之后将指针移到下一个数据。得到的是Object类型的数据。

迭代器

概述:为了方便地访问集合内容的元素,我们把取出方式定义在集合内部。取出方式就被定义为内部类。

每一个容器的数据结构不同,所以取出的动作细节不一样,但是都有共性的内容判断和取出。那么可以写共性抽取从而形成具备此功能的类Iterator。并通过一个对外提供的方法:.iterator()获得多内部数据操作的一个工具。

 

迭代器方法:

1、 获取下一个数据

2、 判断是否还有下一个数据

3、 删除某个数据

Collection类的两个子类:

1、 List:元素都是有序的,元素可以重复。

2、 Set:元素都是无序的,元素不可以重复。

List结合容器

List容器特有方法:(凡可操纵脚标的方法都为其特有方法)

增:

 void

add(int index,E element)
          在列表的指定位置插入指定元素(可选操作)。

boolean

addAll(int index,Collection<? extendsE> c)
          
将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。

 

删:

 E

remove(int index)
          移除列表中指定位置的元素(可选操作)。

 

 E

set(int index,E element)
          用指定元素替换列表中指定位置的元素(可选操作)。

 

 E

get(int index)
          返回列表中指定位置的元素。

 List<E>

subList(int fromIndex, int toIndex)
         
 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

ListIterator<E>

listIterator(int index)
          
返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

 int

indexOf(Object o)
         
 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

 

集合容器并发访问错误:

不能对同一元素进行不同方式的操作:

Eg:Iterator  it = a1.iterator(); // 并发访问错误。

         a1.add(“java001”);

分析:既用了迭代器有用到了原对象,从而引发并发修改异常。

 

并发访问错误的原因:

Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出java.util.ConcurrentModificationException 异常。

Iterator迭代器的操作方法:

boolean

hasNext()
          如果仍有元素可以迭代,则返回 true。

 E

next()
          返回迭代的下一个元素。

 void

remove()
          从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。

 

 

 

List集合容器迭代器ListIterator的特点:

特点:因为List有脚标,所以其持有的迭代器可以对元素进行操作。

在使用迭代器时,不能通过集合对象方法操作集合中的元素。可是iterator方法有限,只能对元素进行判断,取出,删除操作。若要想进行其他操作eg添加、修改。就需要使用其子接口:ListIterator;

其特有的方法:

void

add(E e)
          将指定的元素插入列表(可选操作)。

boolean

hasPrevious()
          
如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。

 int

nextIndex()
          
返回对 next 的后续调用所返回元素的索引。

 E

previous()
          
返回列表中的前一个元素。

 int

previousIndex()
          
返回对 previous 的后续调用所返回元素的索引。

 void

set(E e)
         
 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。

 

List的子派系:

ArrayList:底层数据结构采用的是数组结构(查询块,增删慢)

LinkList:底层数据结构使用的是链式结构(查询慢,增删块)

Vector:底层是数组结构。(和ArrayList功能一致,只是Vector出现于JDK1.0,而那时集合还未出现,因此在如今,其已被ArrayList取代。)

 

ArrayList  “vs” Vector

1、 ArrayList线程不同步,Vector线程同步(ArrayList 替代了 Vector)

2、 ArrayList开始长度为10,以50%延长;Vector开始长度为10,以100%延长。

Vector的特别之处:利用枚举进行取数(类似迭代器)

Vector取数方式:

1、 增:

 void

addElement(E obj)
          将指定的组件添加到此向量的末尾,将其大小增加 1。

 void

insertElementAt(E obj, int index)
          将指定对象作为此向量中的组件插入到指定的 index 处。

 

2、 删

 void

removeAllElements()
          从此向量中移除全部组件,并将其大小设置为零。

 boolean

removeElement(Object obj)
          从此向量中移除变量的第一个(索引最小的)匹配项。

 void

removeElementAt(int index)
          删除指定索引处的组件。

 

3、 改

 void

setElementAt(E obj, int index)
          将此向量指定 index 处的组件设置为指定的对象。

 

4、 查

 E

firstElement()
          返回此向量的第一个组件(位于索引 0) 处的项)。

 

5、 迭代器

Enumeration<E>

elements()
          返回此向量的组件的枚举。

 

6、 遍历


Vector的枚举变量:Enumeration

 boolean

hasMoreElements()
          测试此枚举是否包含更多的元素。

 E

nextElement()
          如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

Vector的枚举仅有两种方法。与迭代器很类似。(其实他们方法一致,因此在升级后被迭代器锁取代)

注:有Element的操作都为Vector的特有操作。

LinkedList集合容器

LinkList特有方法:

 void

addFirst(E e)
          将指定元素插入此列表的开头。

 void

addLast(E e)
          将指定元素添加到此列表的结尾。

JDK1.6后出现的新方法:

boolean

offerFirst(E e)
          在此列表的开头插入指定的元素。

 boolean

offerLast(E e)
          在此列表末尾插入指定的元素。

 

 E

removeFirst()
          移除并返回此列表的第一个元素。

 E

removeLast()
          
移除并返回此列表的最后一个元素。

若没有元素,会产生异常NoSuchElementException

JDK1.6后出现的新方法:

 E

pollFirst()
          获取并移除此列表的第一个元素;如果此列表为空,则返回 null。

 E

pollLast()
          获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。

 

 E

getFirst()
          返回此列表的第一个元素。

 E

getLast()
          返回此列表的最后一个元素。

若没有元素,会产生异常NoSuchElementException

JDK1.6后出现的新方法:

 E

peekFirst()
          获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。

 E

peekLast()
          获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。

通过LinkedList实现队列:

 

实例:


在39行,判断数据是否存在时,会调用到Person对象的比较方法equals。为此,我们需要在Person中复写比较方法,以保证比较方式为我们所期望的方式。删除方法也依赖equals方法。

Set集合容器

特点:其中存储的是无序不可以重复元素。

其方法和Collection一致。

HashSet:

底层数据结构是哈希表,线程非同步;

特点:


(保证元素唯一性的方法:先通过判断哈希code,若相同则继续判equals方法

因此,为了保证两个方法都能正常使用,我们需要依据情况复写为我们需要的方法。

在求哈希值时,应该尽量保证哈希值的唯一性。

只要是涉及到元素比较的方法时,对于HashSet来说一定要用到hashCode()和equals()方法。

注意:

常犯的错误:1、equals的参数为Object,为了能复写equals方法必须保证参数一致

                                             2、hashCode很容易写错。

存储结构:

Eg:Person类;

P1 = Person(”zhansan1”,49),哈希值:66;

P2 = Person(”zhansan2”,45),哈希值:66;

P3 = Person(”zhansan1”,49),哈希值:66;

P4 = Person(”zhansan4”,33),哈希值:56;

P5 = Person(”zhansan5”,45),哈希值:44;

 

P5   

P4   

P1  

    

    

 

 

P2

 

 

 

 

 

 

 

 

 

 

 

 

P3因为哈希值和通过equals方法和p1的都一样,因此被判断为同一个数据并被移除。

TreeSet:

可以对Set集合中的元素进行排序。底层数据结构为二叉树。

特点:

(TreeSet通过CompareTo()实现排序,在排序时首先比较主要内容,再比较较次要内容(主要通过二叉树进行存储)。通过CompareTo()的返回值进行操作,从而确定输出。)

 

TreeSet排序方式:

方式一:让元素自身具备比较性。

元素需要实现Compareable接口,复写compareTo方法。这种方式也成为元素的自然顺序,或者叫做默认顺序。


 

当年龄相同时,我们就需要比较其他数据来确保排序。(TreeSet不能有同一元素)


对于一般的基本数据类型,有自己的compareTo方法。

方式二:让容器自身具备比较性

当元素不具备比较性,或者具备的比较性不是所需要的时,这时就让集合本身具备比较性。在集合初始化时就给他附一个比较器,以使其在初始化就有比较性。

TreeSet(Comparator<? superE> comparator)
          构造一个新的空TreeSet,它根据指定比较器进行排序。


 

注:当两种排序都存在时,以比较器为主。

练习:

字符串通过长度进行排序:




0 0
原创粉丝点击