Java面向对象笔记 • 【第7章 集合】
全部章节 >>>>
本章目录
7.1 集合概述7
7.1.1 Java集合体系概述
为了使程序方便地存储和操纵数目不固定的一组数据,JDK类库中提供了Java集合,所有Java集合类都位于java.util包中。与Java数组不同,Java集合不能存放基本数据类型,而只能存放对象。
Java集合类主要由两个接口派生而出,即Collection和Map接口。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上 |
boolean addAll(int index, Collection collection) | 在index位置后添加容器collection中所有的元素 |
Object get(int index) | 取出下标为index的位置的元素 |
int indexOf(Object element) | 查找对象element在List中第一次出现的位置 |
int lastIndexOf(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。
本文来自博客园,作者:明金同学,转载请注明原文链接:https://www.cnblogs.com/vmuu/p/15663576.html
公众号:【明金同学】