集合框架1

本文深入讲解Java集合框架,包括Collection接口及其子接口如List和Set的特性与使用方法,探讨了集合框架的设计目标及其实现类的特点。同时,介绍了如何使用Iterator进行集合遍历,并解释了相关操作的注意事项。
摘要由CSDN通过智能技术生成

一、集合简介
Java是面向对象的语言,对事物的描述都是以对象的形式。为了方便对多个对象的操作就需要对对象进行存储。但是使用数组存储对象与一些弊端,这时就出现了集合。

集合就像是一个对象的容器,可以动态地存储多个对象,还可以对多个对象进行操作。

Java的集合类可以存储数量不等的多个对象,还可以用于保存具有映射关系的关联数组。

数组在内存存储方面的缺点:

数组初始化后,长度确定。
数组声明的类型,就决定了进行元素初始化时的类型。
总结来说就是,长度固定,类型单一
数组在存储数据时的弊端:

数组初始化以后,长度就不可变了,不便于扩展
数组中提供的属性和方法少,不便于进行添加、删除、插入等操作,且效率不高。同时无法直接获取存储元素的个数
数组存储的数据是有序的、可以重复的。对于无序的不可重复的需求不能满足。存储数据的特点单一。
总结来说:存储数据类型单一,操作性差、不利于扩展
二、集合框架简介
集合框架的设计成要满足以下几个目标。

该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
对一个集合的扩展和适应必须是简单的。
因此,整个集合框架就围绕一组标准接口而设计。你可以直接使用这些接口的标准实现,诸如: LinkedList, HashSet, 和 TreeSet 等,除此之外你也可以通过这些接口实现自己的集合。

  1. 集合框架体系
    img

从上面的集合框架图可以看出,Java 集合可分为 Collection 和 Map 两种体系:

Collection接口:单列数据,定义了存取一组对象的方法的集合

List接口:

元素有序、可重复的集合。
List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector>
Set接口:

元素无序、不可重复的集合。
Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
Map接口:双列数据,保存具有映射关系key-value对的集合

Java 集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包。

  1. 集合框架的逻辑
    所有的集合框架都包含如下内容:

接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。

算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

img

定义接口,具体类实现了接口,重写接口类中的抽象方法,使其具备对应的功能。而重写这些方法运用到了一些算法。

三、Collection接口
Collection接口是Java集合框架的一大分支体系。

Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。
在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 JDK 5.0 增加了泛型以后,Java 集合可以记住容器中对象的数据类型。

  1. Collection接口中的方法
    功能 方法 作用
  2. 添加 add(Object obj) 为集合中添加一个对象obj
    addAll(Collection coll) 添加集合coll中的所有对象到现有集合
  3. 获取有效元素的个数 int size() 返回该集合内元素的个数
  4. 清空集合 void clear() 清空集合内所有元素
  5. 是否是空集合 boolean isEmpty() 判断该集合是否是空集合
  6. 是否包含某个元素 boolean contains(Object obj) 判断该集合中是否含有对象obj
    boolean containsAll(Collection c) 判断该集合中是否含有集合c中的所有对象
  7. 删除 boolean remove(Object obj) 删除集合中的元素obj
    boolean removeAll(Collection coll) 删除该集合中所有和集合coll中相同的元素
  8. 取两个集合的交集 boolean retainAll(Collection c) 取当前集合和集合c的交集,结果放在当前集合中,不影响集合c内的元素
  9. 集合是否相等 boolean equals(Object obj) 判断该集合和obj是否相等
  10. 转成对象数组 Object[] toArray() 将该集合转换为数组,数组内每个元素都是对象
  11. 获取集合对象的哈希值 hashCode() 返回集合对象的哈希值
  12. 遍历 iterator() 返回迭代器对象,用于集合遍历
    import java.util.;
    public class Demo01 {
    public static void main(String[] args) {
    //创建一个ArrayList类,ArrayList类实现了集合Collection接口及其子接口
    Collection coll = new ArrayList();
    //1. add(Object obj):将obj添加到当前集合中
    coll.add(123); //这里相当于自动装箱,转为了包装类对象,因为集合里的元素都是对象而不是数值类型
    coll.add(456);
    coll.add(789);
    coll.add(new String(“Tom”));
    coll.add(false);
    coll.add(new Person(“Jerry”,18));
    System.out.println(coll);
    //2.size():返回当前集合中元素的个数
    System.out.println(“当前集合中元素的个数:” + coll.size());
    //3. isEmpty(): 判断当前集合是否是空集合
    System.out.println(“当前集合是否是空集合:” + coll.isEmpty());
    System.out.println("
    “);
    //4. contains(Object obj):判断当前集合中是否包含obj
    boolean con = coll.contains(123);
    System.out.println(con);
    //contains方法判断集合内是否含有obj,会调用obj所在类的equals方法进行比较。String类重写了Object类中的equals方法,因此比较的是字面值(内容),这里的返回结果是true
    System.out.println(coll.contains(new String(“Tom”)));
    //Person类没有重写Object类中的equals方法,因此比较的是地址值,因此这里的返回结果是false
    System.out.println(coll.contains(new Person(“Jerry”, 18)));
    //总结:向Collection接口的实现类的对象中添加obj对象时,应该重写obj所在类的equals方法
    //5. containsAll(collection coll):判断形参coll所有元素是否在当前集合中
    Collection coll2 = Arrays.asList(123,456);
    System.out.println(coll.containsAll(coll2));
    Collection coll3 = Arrays.asList(123,4567);
    System.out.println(coll.containsAll(coll3));
    System.out.println(”
    “);
    //6. remove(Object obj):移除集合中的obj对象
    //既然要移除obj,肯定会先进行判断,判断集合中的哪个元素是obj,因此也会调用obj所在类的equals方法。因此也应进行重写
    coll.remove(123);
    System.out.println(coll);
    //当没有重写Person类中的equals方法时,该语句不能将集合中的Person{name=‘Jerry’, age=18}删除,重写后则可以
    coll.remove(new Person(“Jerry”, 18 ));
    System.out.println(”
    “);
    //7. removeAll(Collection c):移除集合中所有和集合c中相同的元素,c中可以含有和该集合不同的元素(相当于求差集操作)
    //同样会用到集合中各对象的equals方法,需要重写
    Collection coll4 = Arrays.asList(456,true);
    coll.removeAll(coll4);
    System.out.println(coll);
    System.out.println(”
    ");
    //8. retainAll(Collection c):将该集合和集合c
    有的元素提取出来赋给当前集合(相当于求交集操作),不会影响集合c里的元素
    //同样用到了equals方法,需要重写.这里没有进行重写,所以把原集合中的 Person{name=‘Jerry’, age=18}也去掉了
    Collection coll5 = Arrays.asList(789,“Tom”,new Person(“Jerry”, 18));
    coll.retainAll(coll5);
    System.out.println(coll);
    System.out.println("
    “);
    //9. equals(Object obj):要想返回true,需要原集合和形参obj的所有元素都相同
    //对于List接口的实现类的对象,还要求元素顺序都相同;
    //对于Set接口的实现类的对象,则只用所有元素相同即可,顺序不做要求
    //10. hashcode():返回当前对象的哈希值
    System.out.println(coll.hashCode());
    System.out.println(”
    “);
    //11. toArray():将该集合转换为数组,数组内每个元素都是对象,数组类型根据元素类型确定
    Object[] arr = coll.toArray();
    for (int i = 0; i < arr.length;i++) {
    System.out.println(arr[i]);
    }
    //扩展:数组转化为集合:调用Array类的静态方法asList()
    //注意形参应该是包装类对象
    List list = Arrays.asList(new String[]{“aa”, “bb”, “cc”});
    System.out.println(list);
    System.out.println(”
    ********************");
    //12. clear():清空数组
    coll.clear();
    System.out.println(coll);
    //13.iterator():返回Iterator接口的实例,用于遍历集合元素
    }
    }
    class Person {
    //创建私有属性
    private String name;
    private int age;
    //提供一个无参构造器
    public Person() {
    }
    //提供一个有参构造器
    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }
    //重写toString方法,使其返回属性值
    @Override
    public String toString() {
    return “Person{” +
    “name='” + name + ‘’’ +
    “, age=” + age +
    ‘}’;
    }
    //提供访问和设定私有属性的public方法getter和setter
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    }

运行结果:
[123, 456, 789, Tom, false, Person{name=‘Jerry’, age=18}]
当前集合中元素的个数:6
当前集合是否是空集合:false
*********************
true
true
false
true
false
*********************
[456, 789, Tom, false, Person{name=‘Jerry’, age=18}]
*********************
[789, Tom, false, Person{name=‘Jerry’, age=18}]
*********************
[789, Tom]
*********************
109694
*********************
789
Tom
[aa, bb, cc]
*********************
[]
注意点:

集合中删除、相等、取交集、取差集等操作会调用集合中对象所在类的equals方法,因此应该重写集合内元素所在类的equals方法,使其比较内容值,而不是地址。

  1. Interator接口(迭代器)
    2.1 迭代器简介
    Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。

GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

迭代器模式,就是为容器而生。

Iterable接口有一个iterator()方法,Collection接口继承了Iterable接口,因此,所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。

Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。

集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。

2.2 迭代器的方法
hasNext()方法与next()方法:

import java.util.*;
public class Demo01 {
public static void main(String[] args) {
//创建一个ArrayList类,ArrayList类实现了集合Collection接口及其子接口
Collection coll = new ArrayList();
coll.add(123); //这里相当于自动装箱,转为了包装类对象,因为集合里的元素都是对象而不是数值类型
coll.add(456);
coll.add(789);
coll.add(new String(“Tom”));
coll.add(false);
coll.add(new Person(“Jerry”, 18));
//为该集合创建一个迭代器Iterator
//如果需要创建Iterator 对象,则必须有一个被迭代的集合。
Iterator iterator = coll.iterator();
//调用迭代器的hasNext()方法和next()方法;
//生成迭代器对象,相当于创建了一个指针,指针指向集合中第一个元素的前边
//hasNext()方法:判断是否还有下一个元素
while (iterator.hasNext()) {
//next()方法:指针下移,将下移义后的集合位置上的元素返回
System.out.println(iterator.next());
}
}
}
class Person {
//创建私有属性
private String name;
private int age;
//提供一个无参构造器
public Person() {
}
//提供一个有参构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//重写toString方法,使其返回属性值
@Override
public String toString() {
return “Person{” +
“name='” + name + ‘’’ +
“, age=” + age +
‘}’;
}
//提供访问和设定私有属性的public方法getter和setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

运行结果:
123
456
789
Tom
false
Person{name=‘Jerry’, age=18}
迭代器的原理:

生成迭代器对象,相当于创建了一个指针,指针指向集合中第一个元素的前面
hasNext()方法:判断是否还有下一个元素
next()方法:指针下移,将下移义后的集合位置上的元素返回
迭代器的错误使用:

Iterator iterator = coll.iterator();
//这样相当于指针下移两次,将会跳着输出,还会报异常
while (iterator.Next() != null) {
System.out.println(iterator.next());
}
//集合每次调用iterator()方法,都会返回一个新的迭代器对象,这样每次都会出现一个新指针,指向集合第一个元素的前面,因此该语句块直回不停输出集合内的第一个元素。
while (coll.iterator().hasNext() != null) {
System.out.println(iterator.next());
}
remove()方法:

import java.util.*;
public class Demo01 {
public static void main(String[] args) {
//创建一个ArrayList类,ArrayList类实现了集合Collection接口及其子接口
Collection coll = new ArrayList();
coll.add(123); //这里相当于自动装箱,转为了包装类对象,因为集合里的元素都是对象而不是数值类型
coll.add(456);
coll.add(789);
coll.add(new String(“Tom”));
coll.add(false);
coll.add(new Person(“Jerry”, 18));
System.out.println(coll);
//生成一个迭代器,遍历集合,当发现集合中”Tom“对象时,利用iterator.remove()方法将其删除
Iterator iterator = coll.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
if (“Tom”.equals(obj)) {
//iterator内部定一个了一个remove()方法,可以在遍历集合的时候删除集合中的元素,该方法不同于集合直接调用remove方法
iterator.remove();
}
}
//当遍历结束,上述迭代器失效,若要在其遍历集合,需要重新调用集合的iterator()方法生成一个迭代器
//重新遍历输出集合中的元素
iterator = coll.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
class Person {
//创建私有属性
private String name;
private int age;
//提供一个无参构造器
public Person() {
}
//提供一个有参构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//重写toString方法,使其返回属性值
@Override
public String toString() {
return “Person{” +
“name='” + name + ‘’’ +
“, age=” + age +
‘}’;
}
//提供访问和设定私有属性的public方法getter和setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

运行结果:
[123, 456, 789, Tom, false, Person{name=‘Jerry’, age=18}]
123
456
789
false
Person{name=‘Jerry’, age=18}
如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报illegalStateException异常
3. for-each循环遍历集合
Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。

该遍历操作不需获取Collection或数组的长度,无需使用索引访问元素。
遍历集合的底层调用Iterator完成操作。
for-each还可以用来遍历数组。
语法:

for(集合元素的类型 局部变量名 : 集合名称)

for-each循环遍历集合:

for (Object j : coll) {
System.out.println(j);
}
for-each循环遍历数组:

int[] arr = new int[]{1,2,3,4}
for (int j : arr) {
System.out.println(j);
}
for-each循环遍历字符串:

String[] str = new String[]{1,2,3,4}
for (int j : str) {
System.out.println(j);
}
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明,KuangStudy,以学为伴,一生相伴!

本文链接:https://www.kuangstudy.com/bbs/1380775553455484930

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值