Java OOP 集合框架

目录

一、数组存在的缺陷

二、Java集合框架

 三、Collection接口

 四、Collection接口示例

 五、迭代器Iterator

 六、使用foreach循环遍历集合元素

 七、List接口

 八、LinkedList类

 九、Set接口

 十、HashSet类

十一、Map接口

 十二、Map的遍历

十三、Map.Entry接口

 十四、Hashtable类

 十五、本章总结


一、数组存在的缺陷

丰收季节,使用一个长度为5的一维数组记录每家果商需要的水果品类数量

 

结论:

​    数组长度固定不变
   不便存储具有映射关系的数据
​    数据变更效率低下
经验

​      如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架

二、Java集合框架

Java 集合框架

  提供了一套性能优良、使用方便的接口和类
  位于java.util包中
  集合中的元素全部是对象,即Object类的实例
  不同的集合类有不同的功能和特点,适合不同的场合

 Collection 接口存储一组不唯一,无序的对象

Map接口存储一组键值对象,提供key到value的映射

 

 三、Collection接口

Collection接口是List、Set接口的父接口

接口里定义的方法即可用于操作Set集合,也可用于操作List集合

常用方法

方法描述
boolean add(Object o)用于向集合中添加一个元素 如果集合不允许重复且已包含了指定元素,则返回false
boolean addAll(Collection c)将集合c里所有元素添加到指定集合里。添加成功返回true
void clear()清除集合中所有元素,将集合长度变为为0
boolean contains(Object o)  判断集合中是否包含指定元素
boolean containsAll(Collection c)判断集合中是否包含集合c里所有的元素
boolean remove(Object o)删除集合中的指定元素o。当集合中包含了一个或多个元素o时,这些元素将被删除。删除成功,返回true
int size()  返回集合里元素的个数
boolean retainAll(Collection c)从集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合和集合c的交集) 如果该操作改变了调用该方法的集合,则返回true
boolean removeAll(Collection c)从集合中删除集合c里包含的所有元素 如果删除了一个或一个以上的元素,则返回true
boolean isEmpty()如果此集合中不包含任何元素,则返回true
Object[] toArray()该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素

 四、Collection接口示例

使用Collection集合实现下面功能

  存储果商采购的水果品类信息
  获取水果品类总数
  删除指定的品类数据
  判断集合中是否包含指定数据
  输出全部水果品类信息
  清空集合

/**
 * ClaName:CollectionTest
 * Description:TODO
 * date:2022/4/4 11:59
 *
 * @author Reincarnation
 * @version 1.0
 * @since JDK 1.8
 */

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public class CollectionTest {
    public static void main(String[] args) {
        Collection fruitList1=new ArrayList();
        //添加元素
        System.out.println("********添加元素add()********");
        fruitList1.add("香水梨");
        fruitList1.add("苹果梨");
        fruitList1.add("皇冠梨");
        //虽然集合里不能放基本类型值,但是Java支持自动封装
        fruitList1.add(5);
        System.out.println("第1个集合里的元素:"+fruitList1);
        System.out.println("********删除元素remove()********");
        fruitList1.remove(5);
        System.out.println("第1个集合里的元素:"+fruitList1);
        System.out.println("********获取元素个数size()********");
        System.out.println("第1个集合一个添加了"+fruitList1.size()+"类水果信息。");
        System.out.println("********判断集合是否包含指定元素contains()********");
        System.out.println("第1个集合中是否包含富士苹果?"+fruitList1.contains("富士苹果"));
        System.out.println("********判断集合包含关系containsAll()********");
        Collection fruitList2=new HashSet();
        fruitList2.add("香水梨");
        fruitList2.add("苹果梨");
        fruitList2.add("富士苹果");
        fruitList2.add("金帅苹果");
        System.out.println("第2个集合里的元素:"+fruitList2);
        System.out.println("第2个集合是否包含第1个集合?" +fruitList2.containsAll(fruitList1));
        fruitList1.remove("皇冠梨");
        System.out.println("第2个集合是否包含第1个集合?" +fruitList2.containsAll(fruitList1));
        System.out.println("********只保留集合共同元素retainAll()********");
        fruitList2.retainAll(fruitList1);
        System.out.println("第2个集合里的元素:"+fruitList2);
        System.out.println("********删除集合2全部元素clear()********");
        fruitList2.clear();
        System.out.println("第2个集合里的元素:"+fruitList2);
    }
}

注意:

​     集合中存储元素为Object类型对象,属于引用数据类型,默认调用Object类toString()方法执行输出操作
​    本示例输出集合元素时,调用String类重写的toString()方法

 五、迭代器Iterator

System.out.println()方法以[ele1,ele2,…]形式输出集合全部元素

   因为所有的Collection实现类都重写了toString()方法
如果遍历集合的每一个元素,并对其进行操作呢?

方法一:使用Iterator接口遍历集合元素

  获取Iterator :Collection 接口的iterator()方法
  Iterator接口定义的方法

方法描述
boolean hasNext()是否存在下一个迭代元素,存在则返回true
Object next()返回迭代的下一个元素
void remove()删除集合里上一次next()方法返回的元素


方法二:使用foreach循环遍历集合元素

记录水果更完整的信息,除了品类之外,还需要记录每类水果的价格,遍历集合输出每类水果的品类和价格信息

苹果梨,每斤2.0元。
金帅苹果,每斤3.0元。
香水梨,每斤2.5元。
富士苹果,每斤3.5元。

使用Iterator对象实现

定义Fruit类,描述水果对象
定义测试类,向集合中添加数据和遍历集合

/**
 * ClaName:Fruit
 * Description:TODO
 * date:2022/4/4 18:18
 *
 * @author Reincarnation
 * @version 1.0
 * @since JDK 1.8
 */

/**
 * 水果类
 */
public class Fruit {
    private String brand;   //水果品种
    private double price;   //价格

    public Fruit(){}
    public Fruit(String brand,double price){
        this.brand=brand;
        this.price=price;  //每斤价格
    }
    //输出信息
    public void show(){
        System.out.println(this.brand+",每斤"+this.price+"元。");
    }

    public String getBrand() {
        return brand;
    }
}

Iterator

  Iterator的使用必依赖于Collection对象
  Iterator仅用于遍历集合,并不提供储存数据的功能
  使用Iterator迭代访问Collection集合时,可调用Iterator的remove()方法删除集合元素

/**
 * ClaName:Fruit
 * Description:TODO
 * date:2022/4/4 18:18
 *
 * @author Reincarnation
 * @version 1.0
 * @since JDK 1.8
 */

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

/**
 * 使用Iterator接口遍历集合
 */
class IteratorTest{
    public static void main(String[] args) {
        //创建一个集合
        Collection fruitList=new HashSet();
        Fruit fruit1=new Fruit("香水梨",2.5);
        Fruit fruit2=new Fruit("苹果梨",2.0);
        Fruit fruit3=new Fruit("富士苹果",3.5);
        Fruit fruit4=new Fruit("金帅苹果",3.0);
        //添加元素
        fruitList.add(fruit1);
        fruitList.add(fruit2);
        fruitList.add(fruit3);
        fruitList.add(fruit4);
        //使用System.out.println()输出结果
        //System.out.println(fruitList);
        //获取集合迭代器
        Iterator it=fruitList.iterator();
        while (it.hasNext()){
            Fruit fruit=(Fruit) it.next();
            fruit.show();
        }
    }
}


注意事项

使用Iterator对集合元素进行迭代时,是把集合元素的值传给迭代器,因此,删除迭代器中存储的值不会影响集合中保存的元素

常见错误

对Collection集合进行遍历操作时,其中的元素不能被改变

Iterator it = fruitList.iterator();
while(it.hasNext()) {
     Fruit fruit = (Fruit)it.next();
     if(fruit.brand.equals("苹果梨")) {
           fruit.remove();
      } else {
           fruit.show();
      }
}

运行结果 引发ConcurrentModificationException异常

 六、使用foreach循环遍历集合元素

foreach循环

JDK1.5引入的语法结构,也称为增强for循环
可用于遍历集合和数组

for(数据类型type 迭代变量名value:迭代对象object) {
     //引用迭代变量value的语句
}

使用foreach循环遍历水果品类集合

for(Object obj:fruits) {
    Fruit fruit = (Fruit)obj;
    fruit.show();
}

注意:

与Iterator接口类似,foreach循环中迭代变量也不是集合元素本身,系统只是依次把集合元素的值赋给迭代变量。因此,在foreach循环中修改迭代变量的值也没有任何实际意义

 七、List接口

继承Collection接口,存储一组可重复的有序对象

元素顺序以元素插入的次序来放置元素,不会重新排序

通过索引访问数组元素,索引从0开始

根据索引操作集合元素的方法

 

List集合

是List接口所有实现类组成的集合

 

ArrayList类实现长度可变的数组

遍历元素和随机访问元素的效率比较高

 LinkedList类采用双向链表存储方式

插入、删除元素时效率比较高

 使用List集合的注意事项

​    可以使用索引访问List集合元素

​    可以使用for循环遍历List集合

​    List集合中存放的都是Object类对象

​          add(Object o)方法的参数是Object类对象
​          在通过get(int i)方法获取元素时必须进行强制类型转换
​           Fruit fruit = (Fruit)list.get(i);
删除集合元素的方法

   按索引删除 fruits.remove(2);
   按对象删除 fruits.remove(fruit3);
调用set(int index,Object o)方法改变List集合指定索引的元素时,指定的索引必须是List集合的有效索引

set(int index,Object o)方法不会改变List集合的长度

 八、LinkedList类

具有双向链表结构,更加方便实现添加和删除操作

除了具有List接口扩展的方法外,还提供了实现链表操作的方法

方法描述  
void addFirst(Object o)在链表的首部添加元素
void addLast(Object o)在链表的末尾添加元素
Object getFirst()返回链表中第一个元素
Object getLast()返回链表中最后一个元素
Object removeFirst()删除并返回链表中的第一个元素
Object removeLast()删除并返回链表中的最后一个元素

集合的首部或尾部添加、获取和删除水果对象

实现思路及关键代码

   创建集合及元素对象
   向集合中添加元素
   查看集合中第一条水果信息
   查看集合中最后一条水果信息
   删除集合中第一条和最后一条信息

/**
 * ClaName:LinkedListTest
 * Description:TODO
 * date:2022/4/4 18:53
 *
 * @author Reincarnation
 * @version 1.0
 * @since JDK 1.8
 */

import java.util.LinkedList;
import java.util.List;

/**
 * 使用LinkedListTest集合存储数据
 */
public class LinkedListTest{
    public static void main(String[] args) {
        //1.创建一个集合
        LinkedList fruits = new LinkedList();
        Fruit fruit1 = new Fruit("苹果1号", 2.5);
        Fruit fruit2 = new Fruit("苹果2号", 2.0);
        Fruit fruit3 = new Fruit("苹果3号", 3.5);
        Fruit fruit4 = new Fruit("苹果4号", 3.0);
        //2.向集合中添加元素
        fruits.add(fruit1);
        fruits.add(fruit2);
        fruits.add(fruit3);
        fruits.add(fruit4);
        System.out.println("集合中包含水果信息如下: ");
        ArrayListTest.showData(fruits);
        //3.查看集合中第一条水果信息
        Fruit firstFruit=(Fruit)((LinkedList) fruits).getFirst();
        System.out.println("集合中第一类水果:"+firstFruit.getBrand());
        //3.查看集合中最后一条水果信息
        Fruit lastFruit=(Fruit)((LinkedList) fruits).getLast();
        System.out.println("集合中最后一类水果:"+firstFruit.getBrand());
        //3.删除集合中第一条和最后一条信息
        ((LinkedList) fruits).removeFirst();
        ((LinkedList) fruits).removeLast();
        System.out.println("删除部分信息后还有"+((LinkedList) fruits).size()+"条水果信息。如下");
        ArrayListTest.showData(fruits);
    }

    /**
     * 遍历集合
     */
    public static void showData(List list){
        for (int i=0;i<list.size();i++){
            Fruit fruit=(Fruit)list.get(i);
            fruit.show();
        }
    }
}

ArrayList类和LinkedList类对比

ArrayList类和LinkedList类的共同点

​    可以容纳所有类型的元素对象,包括null
   元素值可以重复
   元素按顺序存储
ArrayList类特点

   底层是数组
   优点:基于数组实现,读取操作效率高
   缺点:不适合频繁进行插入和删除操作,因为每次执行该类操作都需要频繁移动其中的元素
LinkedList类特点

​    由双向链表实现,任意一个节点都可以方便地访问它的前驱节点和后继节点
​    优点:增加、删除操作只需修改链表节点指针,不需进行频繁的移动
​    缺点:遍历效率较低

 九、Set接口

和List接口一样,也是Collection的子接口
集合里的多个对象之间没有明显的顺序
不允许包含重复的元素

 与Collection接口基本一样,没有提供额外的方法,只是行为上略有不同

继承关系

 十、HashSet类

是Set接口的典型实现

可以实现对无序不重复数据的存储,具有很好的存取和查找性能

特征

   不允许存储重复的元素
   没有索引,没有包含索引的方法,不能使用索引遍历
   无序集合,存储元素和取出元素的顺序可能不一致
执行添加操作时,会将新添加的对象依次和集合中现有的元素进行比较

   通过执行集合元素的hascode()方法和equals()方法进行判断
   如果集合中不存在所添加的元素,则添加成功;否则,添加失败
不能使用索引进行遍历

使用HashSet集合存储水果信息数据

关键代码

/**
 * ClaName:HashSetTest
 * Description:TODO
 * date:2022/4/4 19:38
 *
 * @author Reincarnation
 * @version 1.0
 * @since JDK 1.8
 */

import java.util.HashSet;
import java.util.Set;

/**
 * 使用HashSetTest集合存储数据
 */
public class HashSetTest {
    public static void main(String[] args) {
        //1.创建一个Set集合和多条水果数据
        Set fruits= new HashSet();
        Fruit fruit1=new Fruit("富士苹果",2.5);
        Fruit fruit2=new Fruit("金帅苹果",2.0);
        //2.向集合中添加元素
        fruits.add(fruit1);
        fruits.add(fruit2);
        System.out.println("添加重复元素,是否成功:"+fruits.add(fruit1));
        //3.遍历集合
        for (Object o:fruits) {
            Fruit fruit=(Fruit)o;
            fruit.show();
        }
    }
}

十一、Map接口

查阅汉英字典,可以通过中文找到对应的英文单词

   由一对一关系的一组中英文数据组成
   是一组成对的键-值对象,而不是单值数据
Java中,使用List和Set无法实现,怎么办?

   使用Map接口
Map接口专门处理键值映射数据的存储

   根据键(key)实现对值(value)的操作
        Key:不要求有序,不允许重复
        Value:不要求有序,但允许重复
与Collection接口不存在继承关系

常用方法


最常用的实现类是HashMap

 

存储成对出现的“键-值对”元素

​     如:京—北京市
一个Map对象由若干个“键-值对”组成

 查询指定元素效率高

使用HashMap集合类实现下面功能

​    建立中国省份或直辖市全称与简称对照关系表
​    通过删除键实现对键值的删除
实现思路及关键代码

​     使用HashMap存储多组省份全称和简称的键值对
​     显示简称为"京"的省份或直辖市全称
​    显示集合中元素个数
​    两次判断Map中是否存在"闽"键
​    分别显示键集、值集和键值对集
​     清空 HashMap并判断
代码示例:

/**
 * ClaName:Test
 * Description:TODO
 * date:2022/4/4 19:49
 *
 * @author Reincarnation
 * @version 1.0
 * @since JDK 1.8
 */

import java.util.HashMap;
import java.util.Map;

/**
 * 测试HashMap集合的多个方法
 */
public class Test {
    public static void main(String[] args) {
        //1.使用HashMap集合存储多组省份或直辖市全称和简称的“键-值对"
        Map provinces=new HashMap();
        provinces.put("京","北京市");
        provinces.put("沪","上海市");
        provinces.put("闽","福建省");
        provinces.put("湘","湖南省");
        //2.显示简称为"京"的省份或直辖市全称
        String province=(String)provinces.get("京");
        System.out.println("“京”对应的省份或直辖市:"+province);
        //3.显示1集合中元素个数
        System.out.println("共记录了"+provinces.size()+"组数据。");
        /*4.两次判断Map集合中是否存在“闽”键*/
        System.out.println("是否记录简称为“闽”的省份或直辖市?"+provinces.containsKey("闽"));
        provinces.remove("闽");
        System.out.println("是否记录简称为“闽”的省份或直辖市?"+provinces.containsKey("闽"));
        /*5.分别显示键集、值集和“键-值对"集*/
        System.out.println(provinces.keySet());
        System.out.println(provinces.values());
        System.out.println(provinces);
        /*6.清空HashMa集合并判断*/
        provinces.clear();
        if (provinces.isEmpty())
            System.out.println("已清空全部数据!");
    }
}

 十二、Map的遍历

使用HashMap集合类存储并输出水果信息
实现思路及关键代码

   创建水果对象

   创建Map集合对象并添加水果元素

   通过迭代器依次输出集合中所有水果信息

使用Iterator迭代器遍历Map集合的步骤

   通过KeySet()方法返回键的集合为Set集合
   循环遍历键的集合,获取每个键对应的值

/**
 * ClaName:MapIteratorTest1
 * Description:TODO
 * date:2022/4/5 9:24
 *
 * @author Reincarnation
 * @version 1.0
 * @since JDK 1.8
 */

import java.util.*;

/**
 * 对Map接口应用泛型
 */
public class MapIteratorTest1 {
    public static void main(String[] args) {
        //1.创建多个水果对象
        Fruit fruit1 = new Fruit("香水梨", 2.5);
        Fruit fruit2 = new Fruit("苹果梨", 2.0);
        Fruit fruit3 = new Fruit("富士苹果", 3.5);
        Fruit fruit4 = new Fruit("金帅苹果", 3.0);
        //2.创建Map集合对象并添加水果元素
        Map<String,Fruit> fruitMap=new HashMap<String, Fruit>();
        fruitMap.put(fruit1.getBrand(),fruit1);
        fruitMap.put(fruit2.getBrand(),fruit2);
        fruitMap.put(fruit3.getBrand(),fruit3);
        fruitMap.put(fruit4.getBrand(),fruit4);
        //3.通过迭代器依次输出集合中所以水果信息
        System.out.println("所以水果数据如下:");
        Set<String> keys=fruitMap.keySet();
        Iterator<String> it= keys.iterator();
        while (it.hasNext()){
            String key=(String)it.next();  //取出key
            Fruit fruit=fruitMap.get(key); //根据key取出对应的value(水果对象)
            fruit.show();
        }
    }
}

注意:

Set集合中每个元素都是一个Map.Entry对象,进行键和值的分离,由于是Object类型,在获取对象之前还需要进行必要的类型转换

十三、Map.Entry接口

用于保存“键-值对”元素

常用方法

方法描述  
Object getKey()取得此“键-值对”对应的key值
Object getValue()  取得此“键-值对”相对应的value值
int hashCode()返回该“键-值对”的哈希码值
Object setValue(Object value)用指定的值替换该“键-值对”的value值

运用Map.Entry接口遍历集合

   通过entrySet()方法获取所有“键-值”对元素的集合
   遍历集合中每个元素,进行键和值的分离

Set allSet = fruitMap.entrySet();  //获取键值对集合
Iterator it = allSet.iterator();
while(it.hasNext()){
    Map.Entry me = (Map.Entry)it.next();
    System.out.println(me.getKey()+" "+((Fruit)me.getValue()).getPrice());
}

 十四、Hashtable类

与HashMap类具有相似的特征,也可以存储“键-值对”元素
是一个古老的Map接口实现类

Hashtable类和HashMap类之间存在的区别

经验:实际开发中,HashMap类使用更多

 十五、本章总结

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值