黑马程序员-----集合



------- android培训java培训、期待与您交流! ----------





1   集合概述

数组可以用来保存多个对象,但是无法确定到底需要保存多少个对象,此时数组将不再适用,因为数组的长度不可变,为了保存这些数目不确定的对象,JDK提供了一些特殊的类,这些类可以存储任意类型的对象,并且长度可变,统称为集合。这些类都位于java.util包中,使用时一定要注意导包问题。


1.1  集合和数组的区别

1  数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。

2  数组中可以存储基本数据类型,集合只能存储对象。

 

1.2  集合类的特点

1  集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

2  集合中存储的都是对象的引用(地址)。

 

1.3  集合的分类

集合按照其存储结构可以分为两大类,即单列集合Collection和双列集合Map,这两种集合的特点具体如下:


1.3.1   单列集合接口Collection

单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。List集合的特点是元素有序、元素可以重复。Set的特点是元素无序并且不可重复。List接口的主要实现类有ArrayList和LinkedList,Set接口的主要实现类有HashSet和TreeSet。


1.3.2  双列集合接口Map

双列集合类的根接口,用于存储具有键(Key)和值(Value)映射关系的元素,每个元素都包含一对键值,在使用Map集合时,可以通过指定的Key找到对应的Value,例如根据一个学生的学号就可以找到对应的学生。Map接口的主要实现类有HashMap和TreeMap

 

1.3.3  集合体系架构图

 

Collection

|--List

      |--ArrayList

      |--LinkedList

      |--Vector

|--Set

      |--HashSet

            |--LinkedHashSet

      |--TreeSet


Map

|--Hashtable

      |--Properties

|--HashMap

      |--LinkedHashMap

|--TreeMap


2   Collection接口

Collection是所有单列集合的父接口,因此在Collection中定义了单列集合的通用的方法,这些方法可以用于操作所有的单列集合

 

方法声明

功能描述

boolean add(Object o)

向集合中添加一个元素

boolean addAll(Collection c)

将集合c中的所有元素添加到该集合中

void clear()

清空集合

boolean remove(Object o)

删除o元素

boolean removeAll(Collection c)

删除指定集合的所有元素

boolean isEmpty()

判断集合是否为空

boolean contains(Object o)

判断集合是否包含o元素

boolean containsAll(Collection c)

判断集合是否包含集合c中的所有元素

Iterator iterator()

返回Iterator迭代器

int size()

获取该集合元素的个数

 

2.1  List集合

2.1.1  List集合概述

在List集合中,允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序是一致的。

List集合具体对象的特点:

ArrayList:底层数据结构使用的是数组结构。特点:查询,修改,速度很快。增加,删除稍慢。(元素越多越慢)构造是一个初始容量为10,按照50%容量扩展。

LinkedList:底层数据结构使用的是链表结构。特点:增加,删除很快。查询,修改很慢。

Vector:底层是数组结构。特点:是同步的。无论增加删除都慢。被ArrayList替代了。

构造是一个初始容量为10,按照100%容量扩展,浪费空间。


2.1.2  List集合常用方法

 

方法声明

功能描述

void add(int index,Object element)

将元素element插入到index处

boolean addAll(int index,Collection c);

将集合c的所有元素插入到index处

Object remove(int index);

删除index索引处的元素并返回

Object removeFirst();

删除第一个元素并返回

Object removeLast();

删除最后一个元素并返回

Object set(int index,Object element)

将index处替换成element,并返回

Object get(int index)

返回index处的元素

int indexOf(Object o)

返回对象o在List集合第一次出现的索引

int lastIndexOf(Object o)

返回对象o在List集合最后一次出现的索引

List subList(int start,int end)

返回从start(含)到end(不含)组成的集合

 

2.1.3  ArrayList集合

ArrayList集合是List接口的一个实现类,是程序中最常见的一种集合,可以将ArrayList看成一个长度可变的数组


 

运行结果:  集合长度:4

第二个元素:stu2

 

2.1.4  Iterator接口

Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。




运行结果: stu1 stu2 stu3 stu4


需要注意的是,当通过迭代器获取ArrayList集合中的元素时,都会将这些元素当作Object类型来看待,如果想得到特定类型的元素,则需要进行强制类型转换。

Iterator的next()方法特别注意如果存在多个时可能会发生错误,如以下代码所示:


 

 

运行时会报出NoSuchElementException异常,原因是每调用一次next()方法,就会遍历下一个元素,由于一共添加了奇数个元素,所以会有元素遍历不到就会报错。即使有偶数个元素都能遍历到,但是两个next()方法都不是针对同一个元素,所以以后尽量保证只调用一次next()方法。

Iterator的局限性:

Iterator迭代器无法添加元素,有局限性,在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生异常。但是List集合特有的迭代器,ListIterator(List集合特有)是Iterator的子接口可以操作集合中的元素。

 

2.1.5  LinkedList集合

ArrayList集合在查询元素时很快,但是在增删元素时效率较低。为了克服这种局限性,可以使用List接口的另一个实现类LinkedList。该集合内部维护了一个双向循环链表,链表中的每一个元素都使用引用的方式来记住它的前一个元素和后一个元素,从而可以将所有元素彼此连接起来。正因为这样的数据结构,LinkedList集合对于元素的增删操作具有很高的效率,针对增删操作定义了一些特有的方法:

 

方法声明

功能描述

Void add(int index,Object element)

在index位置插入element元素

Void addFirst(Object o)

在开头插入o元素

Void addLast(Object o)

在末尾插入o元素

Object getFirst()

返回此列表的第一个元素

Object getLast()

返回此列表的最后一个元素

Object removeFirst()

移除并返回第一个元素

Object removeLast()

移除并返回最后一个元素

 

LinkedList集合不用迭代器遍历的方法:

 



运行结果:stu1 stu2 stu3

 

2.1.6  listIterator接口

listIterator中提供了hasPrevious()方法和previous()方法,通过这两个方法可以实现反向迭代元素,另外还提供了add()方法用于增加元素。

 listIterator特有方法:

 

方法声明

功能描述

Void add(Object o)

将指定元素插入列表

Boolean hasPrevious()

如果逆向遍历,列表有多个元素,返回true

Object previous()

返回列表的前一个元素

Void remove()

移除由next或previous返回的最后一个元素

 

注意,listIterator需要传入集合的长度


 

运行结果:stu3 stu2 java stu1 [stu1,java,stu2,stu3]       

   

2.1.7  Vector集合

Vector集合是List接口的一个实现类,用法与ArrayList完全相同,区别在于Vector集合是线程安全的,而ArrayList集合是线程不安全的。但是由于Vector集合效率比较低,所以一般情况下还是用ArrayList集合,下面重点说下Enumeration接口来遍历Vector集合。


 


运行结果: Leo Jay Marry

 

2.2  Set接口

与List接口不同,Set接口中的元素无序,并且都会以某种规则保证存入的元素不出现重复。

Set接口主要有两个实现类,分别是HashSet和TreeSet。其中,HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。TreeSet则是以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序


2.2.1  HashSet集合

HashSet是Set接口的一个实现类,它所存储的元素是不可以重复的,并且元素都是无序的,当向HashSet集合中添加一个对象时,首先会调用该对象的hashCode()方法来确定元素的存储位置,然后再调用该对象的equals()方法来确保该位置没有重复元素。 如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。

注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode方法和equals方法。


 


运行结果:Leo Jay Marry

 

运行发现重复的String类对象Leo没有被加入集合,这是因为String类已经重写了hashCode()和equals()方法,如果是存入自定义的类,那么记住一定要重写hashCode()和equals()方法,否则不能保证元素不会重复。


 

运行结果:[id=1 name=Leo,id=2 name=Jay,id=3 name=Marry]

需要注意的是 equals(Object obj)里面的参数必须是Object,即使使用泛型也必须是Object,所以务必需要进行类型的转换!

HashSet对象存储过程:


 

 

2.2.2  TreeSet集合

TreeSet集合是Set接口的另一个实现类,它内部采用自平衡的排序二叉树来存储元素,这样的结构可以保证TreeSet集合中没有重复的元素,并且可以对元素进行排序。

保证元素唯一性的依据:compareTo方法return 0

所谓二叉树就是每个节点最多有两个节点的有序树,左侧的子节点称为“左子树”,右侧的子节点称为“右子树”,如果存入 13,8,17,17,1,11,15,25,结构如图所示:

 

 

方法一:通过实现Comparable接口


 


运行结果:[Jay:30,Leo:3,Leo:6,Marry:5]

 

方法二:通过自定义比较器实现comparator接口


 


运行结果:[Leo:3,Marry:5,Leo:6,Jay:30]

需要注意的是,当两种排序方法都存在时,优先按照比较器的方法进行排序!

如果compareTo方法只写return 1,则按存入顺序排序;

如果compareTo方法只写return -1,则按存入顺序的倒序排序!

 

3  Map接口

Map接口是一种双列集合,它的每个元素都包含一个键对象Key和一个值对象Value,键和值对象之间存在一种对应关系,成为映射,从Map集合中访问元素时,只要指定了Key,就能找到对应的Value。Map常用方法如下:

 

方法声明

功能描述

void put(Object key,Object value)

将指定键值对添加进集合

Object get(Object key)

返回指定key对应的value

boolean containsKey(Object key)

判断是否存在指定的key

boolean containsValue(Object value)

判断是否存在指定的value

Set keySet()

获取所有key的视图

Collection<V> values()

获取所有value的视图

Set<Map.entry<K,V>> entrySet()

获取所有的映射关系的视图

 

3.1  HashMap集合

HashMap集合能保证集合中不出现重复的键。

 

 

运行结果:{Marry=5,Jay=30,Jack=6,Leo=6}

 

通过以上结果可以得出如下结论:

1  HashMap集合是无序的

2  键不重复,如果键重复那么值就会覆盖

3  值可以重

 

3.1.1  HashMap集合的遍历方式

1  首先调用Map对象的keySet()方法,获得存储Map中所有键的Set集合,然后通过Iterator迭代器迭代每一个键,最后通过调用get(Object key)方法获得键对应的值。

 

 

 

运行结果:Jay=30 Leo=3 Jack=6 Marry=5

 

2  先获取集合中所有的映射关系,然后从映射关系中取出键和值


 

运行结果:Jay=30 Leo=3 Jack=6 Marry=5

 

3.1.2  获取所有的值

在Map中还提供了一个values()方法,通过这个方法可以直接获取Map中存储的所有值:


 

运行结果:30 3 6 5

 

3.2  LinkedHashMap集合

LinkedHashMap集合使用双向链表来维护内部元素的关系,它是HashMap的子类,可以使迭代出来的元素的顺序和存入的顺序保持一致。


 

运行结果:Leo=3 Marry=5 Jay=30 Jack=6

 

3.3  TreeMap集合

TreeMap集合中是通过二叉树的原理来保证键的唯一性,因此TreeMap集合中所有的键是按照某种顺序进行排列的。


3.3.1  通过实现Comparable接口的方法


 

 

运行结果:{Jay:30=TaiWan,Leo:5=HanGuo,Marry:6=HuNan}

需要注意的是,TreeMap集合是按照键进行排序的,无法通过值进行排序!


3.3.2  通过自定义比较器的方法


 

运行结果:{Leo:5=HanGuo,Marry:6=HuNan,Jay:30=TaiWan}

 

3.4  Properties集合

Map接口中还有一个实现类Hashtable,它和HashMap十分相似,区别在于Hashtable是线程安全的,但是由于存取元素很慢,目前基本上被HashMap所取代了。但Hashtable类中有一个子类Properties在实际应用中非常重要,在实际开发中经常使用Properties集合来存取配置信息。


 

运行结果:  color=red

    margin-top=20px

    font-size=14px

 

4  集合API

JDK中提供了两个工具类专门用来操作集合,一个是Collections,它位于java.util包中。一个是Arrays,也位于java.util包中。


4.1  Collections工具箱

方法声明

功能描述

static boolean addAll(Collection c,T...elements)

将所有指定元素添加到指定的collection集合

static void reverse(List list)

反转指定List集合中的元素顺序

static void shuffle(List list)

对List集合中的元素进行随机排序

static void sort(List list)

根据元素自然顺序对List集合中的元素排序

static void swap(List list,int i,int j)

将指定List集合中i处元素和j处元素交换

static int binarySearch(List list,Object key)

使用二分法搜索指定对象在List集合的索引,List集合的元素必须是有序的

static Object max(Collection col)

根据元素自然顺序返回集合中最大的元素

static Object min(Colllection col)

根据元素自然顺序返回集合中最小的元素

static boolean replaceAll(List list,Object oldVal,Object  newVal)

用一个新的newVal替换List集合中所有的旧值oldVal

 

 

运行结果:

 

 

4.2  Arrays工具箱

Arrays工具箱专门用来操作数组:

 

方法声明

功能描述

static void sort(Object[] arr)

对数组元素进行自然顺序的排序

static int binarySearch(Object[] arr,Object key)

利用二分法查找元素,数组需要先排序

static void copyOfRange(int[] arr,int a,int b)

将数组中指定范围的元素复制到新的数组中

static void fill(Object[] a,Object val)

将指定的值赋给数组中的每一个元素

static String toString(int[] arr)

把数组转换为字符串(可以直接打印)

 

 

运行结果:


 

 

 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值