全部章节   >>>>


本章目录

7.1 集合概述

7.1.1 Java集合体系概述

7.1.2 实践练习

7.2 List集合

7.2.1 ArrayList实现类

7.2.2 LinkedList实现类

7.2.3 实践练习(一)

7.2.4 实践练习(二)

7.3 Set集合和Iterator迭代器

7.3.1 Set集合

7.3.2 Iterator迭代器

7.3.3 实践练习

7.4 Map集合

7.4.1 Map集合

7.4.2 实践练习

总结:


7.1 集合概述7

7.1.1 Java集合体系概述

为了使程序方便地存储和操纵数目不固定的一组数据,JDK类库中提供了Java集合,所有Java集合类都位于java.util包中。与Java数组不同,Java集合不能存放基本数据类型,而只能存放对象。

Java集合类主要由两个接口派生而出,即CollectionMap接口。Collection和Map是Java集合框架的最上层的父接口,这两个接口又包含其他的子接口和实现类。

Java集合主要包括三种类型: Set(集),List(列表),Map(映射)。

Collection集合体系的继承树

实线表示继承关系,虚线表示实现关系

Map体系的继承树

Java集合的三种数据类型存储示意图

1、Set特点

类似于一个罐子,将一个对象添加到Set集合时,Set集合无法记住添加此元素的顺序

Set集合中的元素是不能重复的,否则系统无法准确识别此元素。

2、List特点

类似于一个数组,它可以记录每个元素添加的顺序,但List长度可变。

3、Map特点

Map集合的存放方式,同样类似于一个罐子,但Map集合中的每项数据都由两个值组成。它们分别为key和value,key不可以重复,但是value可以重复。

Collection接口常用方法

方法名

说明

boolean add(Object obj)

向集合中添加一个元素

boolean addAll(Collection c)

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

void clear()

清除集合中的所有元素,此时集合长度变为0

boolean contains(Object obj)

返回集合中是否包含指定的元素

boolean contains(Collection c)

返回集合中是否包含指定的c集合

Boolean  isEmpty()

判断集合是否为空。集合长度为0时返回true,否则返回false

Iterator iterator()

返回一个Iterator对象,用于遍历集合中的元素

boolean remove(Object obj)

删除集合中的指定元素obj,当集合中包含一个或多个元素obj时,仅删除第一个符合条件的元素

int  size()

返回集合中元素的个数

Object[] toArray()

将当前集合转换成一个Object[]类型的数组

7.1.2 实践练习

7.2 List集合

List集合代表一个元素是有序的、且可以重复的、可以为null的集合。

集合中每个元素都有其对应的顺序索引,List集合允许添加重复元素,可以通过索引来访问指定位置的集合元素。

List 的数据结构就是一个序列,存储内容时直接在内存中开辟一块连续的空间,然后将空间地址与索引对应。

List最常见的实现类是ArrayList和LinkedList。

除Collection接口的所有方法之外List还拥有的其他方法

方法名

说明

void add(int index, Object element)

添加对象element到位置index上

booleanaddAll(int index, Collection collection)

在index位置后添加容器collection中所有的元素

Object get(int index)

取出下标为index的位置的元素

intindexOf(Object element)

查找对象element在List中第一次出现的位置

intlastIndexOf(Object element)

查找对象element在List中最后出现的位置

Object remove(int index)

删除index位置上的元素,并返回被删除的这个元素

Object set(int index,Object element)

将index位置上的所示对象替换为element并返回被替换

7.2.1 ArrayList实现类

ArrayList是基于数组实现的List类,ArrayList底层是通过一个长度可变的数组实现的。

ArrayList允许对元素进行快速的随机访问,但是向ArrayList中插入与删除元素的速度较慢。

示例: 演示ArrayList类使用方法

//创建ArrayList对象
ArrayList arrayList=new ArrayList();
arrayList.add("JAVA-DEMO");//向集合中添加字符串对象
arrayList.add(new Hero());//向集合中添加用户自定义对象
System.out.println("arrayList集合的大小="+arrayList.size());
for(int i=0;i<arrayList.size();i++) //遍历集合元素
Object obj=arrayList.get(i); //按照下标获取元素
boolean flag=arrayList.contains("JAVA-DEMO"); //是否包含字符串"JAVA-DEMO"
Object obj=arrayList.remove("JAVA-DEMO");//删除指定元素字符串"JAVA-DEMO"
System.out.println("被删除的元素="+obj);
arrayList.set(0, "ANDROID");//将集合下标为0的元素修改为ANDORID

7.2.2 LinkedList实现类

LinkedList类在实现时,采用链表数据结构,所以向LinkedList中插入和删除元素的速度较快,随机访问速度则相对较慢(随机访问是获取指定下标位置的元素)

LinkedList单独具有addFirst()、addLast()、getFirst()、getLast()、removeFirst()和removeLast()方法。这些方法使LinkedList可以作为堆栈、队列和双向队列来使用。

LinkedList常用方法

方法名

说明

void addFirst(Object o)

将指定元素o插入列表起始位置

addLast(Object o)

将指定元素o添加至列表末尾处

Object removeFirst()

移除并返回列表的首元素

Object removeLast()

移除并返回列表的首末元素

示例:演示LinkedList类使用方法

LinkedList linkedList=new LinkedList();
ArrayList ayList=new ArrayList();
ayList.add("JAVA-DEMO");
ayList.add('中');
//将ayList对象添加至linkedList集合中
linkedList.add(ayList);
//添加自定义类型对象
linkedList.add(new Hero());
linkedList.addFirst(99.8);//向集合头部添加一个元素
Object obj=linkedList.removeFirst();//删除头部元素

示例:比较ArrayList与LinkedList删除元素的效率

ArrayList aList=new ArrayList(); //创建ArrayList集合
System.out.println("==========ArrayList==========");
long bTime=System.currentTimeMillis(); //获取当前系统的时间(毫秒数表示)
System.out.println("起始时间:"+bTime);
for(int i=0;i<100000;i++)
aList.add("DEMO"+i);//向集合中添加数据
int size=aList.size();
for(int i=0;i<size;i++)
aList.remove(0);//每次都删除集合中的第一个元素
long eTime=System.currentTimeMillis();
System.out.println("结束时间:"+eTime);
System.out.println("ArrayList添加、删除所用时间="+(eTime-bTime)+"毫秒");
//创建LinkedList集合
LinkedList lList=new LinkedList();
...
System.out.println("LinkedList添加、删除所用时间="+(edTime-bginTime)+"毫秒");

示例:比较ArrayList与LinkedList访问元素的效率

ArrayList aList=new ArrayList(); //创建ArrayList集合
System.out.println("==========ArrayList==========");
for(int i=0;i<100000;i++)
aList.add("DEMO"+i);//向集合中添加数据
//获取当前系统的时间(毫秒数表示)
long bTime=System.currentTimeMillis();
System.out.println("开始时间:"+bTime);
for(int i=0;i<1000000000;i++)
aList.get(99999); //每次读取列表末尾元素
long eTime=System.currentTimeMillis();
System.out.println("结束时间:"+eTime);
System.out.println("ArrayList随机访问所用时间="+(eTime-bTime)+"毫秒");
LinkedList lList=new LinkedList(); //创建LinkedList集合
System.out.println("==========LinkedList==========");
...
for(int i=0;i<1000000000;i++)
lList.get(99999); //每次读取列表末尾元素
...
System.out.println("LinkedList随机访问所用时间="+(edTime-bgTime)+"毫秒");

经验:

List就是一个线性表接口,而ArrayList、LinkedList又是线性表的两种典型实现,ArrayList   是基于数组的线性表,而LinkedList是基于链表的线性表。

当对集合元素进行频繁的添加或删除操作时,使用LinkedList效率比较高,因为链表的插入和删除操作效率比较高。

当对集合元素进行频繁的读取操作时,使用ArrayList效率比较高,因为基于数组的线性表的随机访问效率比较高。

7.2.3 实践练习(一)

7.2.4 实践练习(二)

7.3 Set集合和Iterator迭代器

7.3.1 Set集合

Set集合,类似于一个瓶子,“装进”Set集合中的多个对象之间没有明显的顺序。

Set集合不允许包含相同的元素,如果试图将两个相同的元素加入同一个Set集合中,则添加操作失败返回false,且新元素不会被加入其集合中。

HashSet是Set接口的最常用的实现类。HashSet按Hash算法实现存储集合中的元素,因为其具有良好的存储和查找性能。

Set的排列顺序可能与添加顺序不同,Set元素值可以是null。

示例:添加Cat对象到HashSet集合

public class Cat {
private String name;
private String color;

public String toString(){ //重新toString()
return "名字:"+this.name+"-"+"毛色:"+this.color;
}
}
public class HashSetTest {
public static void useHashSet(){
HashSet hs=new HashSet();
hs.add("JAVA");
hs.add(new Cat("加菲","黄色"));
hs.add(new Cat("汤姆","青色"));
hs.add(new Cat("加菲","黄色"));
hs.add("JAVA");//添加重复对象"JAVA"
hs.add(100);//添加重复对象"JAVA"
System.out.println("HashSet对象集合="+hs);
}
…..

提问:有两条猫的名字和颜色一摸一样,怎么它们可以一起添加到Set集合?

分析:

这两条猫的名字和颜色一摸一样,但它们equals()返回值为false,hashCode()值也不相等。所以这两条猫不相同。

如果两条猫相同的逻辑是它们名字和颜色相同,则可通过重写Cat类的equals() 和hashCode() 。

示例:重写Cat的equals() 和hashCode()

public  boolean  equals(Object obj){
if(obj==this){
return true;
}else{
if(obj instanceof Cat){
Cat cat=(Cat)obj;
if(this.name.equals(cat.name) && this.color.equals(cat.color))
return true;
else
return false;
}else
return false;
}
}
//重写hashCode()方法
public int hashCode(){
return this.name.hashCode()*this.color.hashCode();
}

重写hashCode()方法的一般规则如下:

在程序运行时,同一个对象的hashCode()方法应该返回相同的值。

当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法应返回相等的值。

象中用作equals()方法比较标准的属性,都应该用于计算hashCode的值。

7.3.2 Iterator迭代器

Iterator接口隐藏了各种Collection实现类的底层细节,该接口提供了遍历Collection集合元素的统一编程接口。

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

由于Set集合中存储的是无序的元素,因此无法在循环中按照下标获取Set集合中的元素,所以利用Iterator接口遍历Set集合中的元素尤为方便。

Iterator常用方法

方法名

说明

boolean hasNext(Object o)

如果被迭代的集合中的元素没有遍历完成,则返回true

Object next()

返回集合中的下一个元素

Void remove()

将迭代器新返回的元素删除

示例:Iterator迭代器应用案例

HashSet  hs=new HashSet();
hs.add(1);
hs.add(new Date());
hs.add("ANDORID");
hs.add(new Cat("加菲","粉色"));
//调用HashSet对象的iterator()方法,返回Iterator实例
Iterator it=hs.iterator();
//使用while循环,循环判断迭代器中是否还有元素
System.out.println("====使用迭代器遍历HashSet集合=====");
while(it.hasNext()){
//获取迭代器中的数据
Object obj=it.next();
System.out.println(obj);
}

7.3.3 实践练习

7.4 Map集合

Map用于保存具有映射关系的数据。Map集合中保存着两组值,一组值用于保存Map里的key,另外一组值保存Map的value。key和value可以为null。

key和value可以是任意类型的数据。Map的key不允许重复,即同一个Map对象的任何两个key通过equals()方法比较总是返回false。

key和value间存在单向一对一关系,即通过指定的key总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value。

HashMap是Map接口最为常用的实现类,HashMap通过哈希码对其内部的映射关系进行快速查找。

7.4.1 Map集合

Map接口常用方法

方法名

说明

put(K key,V value)

向映射中添加一对key与value的映射关系

Object get(Object key)

返回映射中key所对应的value。如果该映射中不包含key,则返回null

putAll(Map  map)

将映射map所有的键值映射关系添加到当前映射

containsKey(Object key)

如果此映射包含指定键的映射关系,则返回true

containsValue(Object value)

如果此映射将一个或多个键映射到指定的value,则返回true

keySet()

将该集合中的所有键对象以Set集合的形式返回

values()

将该集合中的所有值对象以Collection集合的形式返回

remove(Object key)

如果存在指定的键key,则移除该键的映射关系,并返回与该键对象对应的值对象,否则返回null

clear()

从此映射中移除所有映射关系

isEmpty()

如果此映射未包含键-值映射关系,则返回true

size()

返回此映射中的键-值映射关系的数量

示例:HashMap应用案例

Map hm=new HashMap();
hm.put("JAVA", "DEMO");
hm.put("中国", "北京");
hm.put(1, "one");
hm.put(true,"正确" );
hm.put("中国", "上海");
System.out.println("========HashMap集合添加元素后=======");
System.out.println(hm);
System.out.println("====按照Kye获取对应Value值====");
Object value=hm.get("中国");
System.out.println("key值为中国对应的value值="+value);
System.out.println("HashMap集合的大小="+hm.size());
System.out.println("===遍历HashMap集合===");
//返回存储HashMap集合中的所有的key(键)的Set集合
Set set=hm.keySet();
Iterator it=set.iterator();//返回key集合的Iterator迭代器
while(it.hasNext()){//遍历key
Object key=it.next();//得到HashMap集合中的key值
Object val=hm.get(key);//通过key得到对应的value值
System.out.println("键="+key+"\t"+"值="+val);
}

HashMap与Hashtable的区别

HashMap

Hashtable

允许出现空值、空键

不允许出现空值、空键

线程异步,效率较高

线程同步,效率较低

继承自AbstractMap

继承自Dictionary

7.4.2 实践练习

总结:

  • 所有Java集合类都位于java.util包中。与Java数组不同,Java集合不能存放基本数据类型,而只能存放对象。
  • Java集合类主要由两个接口派生而出,即Collection和Map接口。Collection和Map是Java集合框架的最上层的父接口,这两个接口又包含其他的子接口和实现类。
  • List集合代表一个元素是有序的、且可以重复的、可以为null的集合。可以通过get(int index)取出下标为index的元素。
  • List最常见的实现类是ArrayList和LinkedList。当对集合元素进行频繁的读取操作时,使用ArrayList效率比较高;当对集合元素进行频繁的添加或删除操作时,使用LinkedList效率比较高。
  • Set集合不允许包含相同的元素,Set的排列顺序可能与添加顺序不同,Set元素值可以是null,HashSet是Set接口的最常用的实现类。可以通过重写类的equals()和hashCode()方法定义对象相等的逻辑。
  • Iterator迭代器提供了遍历Collection集合元素的统一编程接口。
  • Map用于保存具有映射关系的数据。Map集合中保存着两组值,一组值用于保存Map里的key,另外一组值保存Map的value。key和value可以为null。
  • Map接口的put(K key,V value)用于向映射中添加一对key与value的映射关系,get(Object key)用于返回映射中key所对应的value。

最新文章

  1. java读写Properties属性文件公用方法
  2. Contest 7.23(不知道算什么)
  3. 搭建 Android 开发环境,初试HelloWorld (win7) (下) (转)
  4. Linux学习笔记2——Linux中常用文件目录操作命令
  5. I - Tunnel Warfare - hdu 1540(区间合并更新)
  6. Linux下根据进程的名字杀死进程
  7. C++ - 内置类型的最大值宏定义
  8. 代码的鲁棒性:链表中倒数第k个结点
  9. (七十四)iOS8之前使socket可以后台运行的方法
  10. (N叉树 递归) leetcode589. N-ary Tree Preorder Traversal
  11. [物理学与PDEs]第2章习题13 将 $p$ - 方程组化为守恒律形式的一阶拟线性对称双曲组
  12. oracle性能优化之awr分析
  13. 系统分析与设计个人作业:WordCount
  14. BZOJ3275Number——二分图最大权独立集
  15. SPOJ1557 GSS2 Can you answer these queries II 历史最值线段树
  16. intest
  17. Spring框架学习08——自动代理方式实现AOP
  18. windows Server 2008 R2 开关机取消登录时要按Ctrl+Alt+Delete组合键登录的方法
  19. javascript map forEach filter some every在购物车中的实战演练区分用法
  20. day2作业(基本数据类型,语法)

热门文章

  1. Shell学习(四)——shell中各种括号的作用
  2. Linux环境下为普通用户添加sudo权限
  3. GO 定时器NewTimer、NewTicker使用
  4. 【编程思想】【设计模式】【行为模式Behavioral】迭代器模式iterator
  5. 收集linux网络配置信息的shell脚本
  6. Thymeleaf标准表达式
  7. profile的使用详解
  8. ASP.NET VS 调试提示:指定的端口正在使用中,建议切换到xxx之外并大于1024的端口
  9. 小迪安全 Web安全 基础入门 - 第四天 - 30余种加密编码进制&amp;Web&amp;数据库&amp;系统&amp;代码&amp;参数值
  10. 后端调用WebApi