集合的详细解析

本文介绍了Java集合框架中的Collection接口及其子接口List和Set,重点讲解了ArrayList和LinkedList的特点与操作,Set接口的HashSet和TreeSet实现,以及集合的遍历方式如迭代器和增强型for循环。此外,还讨论了泛型在集合中的应用和集合与数组之间的转换方法。
摘要由CSDN通过智能技术生成

7.集合

介绍

  • 集合和数组一样,可以保存一组数据,并且提供了操作集合元素的相关方法,使用更加方便

  • 迭代器的作用:遍历集合的过程中安全的移除集合中的元素

    Iterator-------迭代器
    在这里插入图片描述

java集合框架中的相关接口

  • Collection—集合
  • java.util.Collection接口:是所有集合的顶级接口,封装了所有集合所共有的方法,下面有多种实现类,因此我们有更多的数据结构可以选择
  • Collection接口下面有两种常见的子接口
    • java.util.List:线性表,是可以重复的集合,并且有序
    • java.util.Set:不可重复集合,大部分实现类是无序的
  • 集合只能存储引用类型元素

List集合

List集合的继承结构图

在这里插入图片描述

List集合的特点
  • 元素按照什么顺序放进去,取出来也是这种顺序
  • 相同的元素可以重复存储
  • List集合中的元素有下标
List集合的常用实现类
  • ArrayList:底层是数组,非线程安全。
  • LinkedList:底层是双向链表。
  • Vector:底层是数组,线性安全。
List集合特有的方法
返回值函数名和形参说明
voidadd(int index,E element)指定下标添加元素,后面的元素往后移
Eremove(int index)删除指定下标的元素,后面的元素往前移
Eget(int index)获取指定下标位置处的元素
Eset(int index,E element)修改指定下标的元素
intindexOf(Object o)获取元素在列表中第一次出现的下标
intlastIndexOf(Object o)获取元素在列表中最后一次出现下标
ListsubList(int from,int to)截取子列表
  • 因为List集合有下标,所以除了使用迭代器遍历,还可以使用for循环方式遍历集合

    循环的条件是list.size()

ArrayList
  • 构造方法

    构造方法说明
    ArrayList()默认初始化一个容量为10的列表
    ArrayList(int initialCapacity)指定容量初始化列表
    ArrayList(Collection<? extends E> c)用Collection集合初始化列表
  • 优点:检索效率较高,向数组末尾添加元素效率高很高

  • 缺点:随机增删元素效率较低,无法存储大量数据

  • 优化:使用ArrayList底层是数组,扩容时效率较低,所以建议在创建ArrayList对象时预估一个容量,也可使用void trimToSize():修正当前列表容量为size大小

LinkedList
  • 构造方法

    构造方法说明
    LinkedList()初始化一个空列表
    LinkedList(Collection<? extends E> c)用Collection集合初始化列表
  • 实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。

    linkedList常用的方法

    返回值函数名和形参说明
    voidaddFirst(E e)将指定元素插入此列表的开头
    voidaddLast(E e)将指定元素添加到此列表的结尾
    EgetFirst()返回此列表的第一个元素(链表为空,抛出NoSuchElementException)
    EgetLast()返回此列表的最后一个元素
    EremoveFirst()移除并返回此列表的第一个元素
    EremoveLast()移除并返回此列表的最后一个元素
    EpeekFirst()获取但不移除此列表的第一个元素(链表为空,返回null)
    EpollFirst()获取但不移除此列表的第一个元素(列表为空,返回 null)
  • 优点:随机增删元素效率较高(链表增删元素不涉及到大量元素的位移)

  • 缺点:查找效率较低(内存空间不是连续的)

Set集合

Set结合继承结构图

在这里插入图片描述

Set集合特点
  • 元素按一定顺序放入集合,不一定会按原顺序取出
  • Set集合中的元素没有下标
Set集合的子接口SortedSet集合的特点
  • 元素按一定顺序放入集合,不一定会按原顺序取出
  • Set集合中的元素没有下标
  • 存放到该集合中的元素会按照大小自动排序
实现类
  • Set接口的实现类 ----- HashSet:

    • 创建HashSet集合对象时,底层实际上new了一个HashMap对象,其key值用来存放HashSet的元素。
  • SortedSet接口的实现类 ----- TreeSet:

    • 创建TreeSet集合时,底层实际上new了一个TreeMap对象,其key值用来存放TreeSet的元素
构造方法
  • HashSet

    构造方法说明
    HashSet()创建一个默认容量为16,加载因子为0.75的集合对象
    HashSet(Collection<? extends E> c)用Collection集合初始化
    HashSet(int initialCapacity)设置指定容量初始化
    HashSet(int initialCapacity, float loadFactor)设置指定容量和加载因子初始化
  • TreeSet

    构造方法说明
    TreeSet()创建一个空集合
    TreeSet(Collection<? extends E> c)用Collection集合初始化
    TreeSet(SortedSet<? extends E> c)用SortedSet集合初始化
    TreeSet(Comparator<? super E> comparator)设置一个比较器来初始化集合

Collection常用方法

  • 练习的材料🎟

    //点
    public class Point {
        private int x;
        private int y;
        //构造方法,重写toString,重写equals,重写set和get
    }
    
  • 集合是存放的是元素的引用

    public class CollectionDemo3 {
        public static void main(String[] args) {
            Collection c = new ArrayList();
            Point p = new Point(1,2);
            c.add(p); //将p添加到集合c中
            System.out.println("p:"+p); //(1,2)
            System.out.println("c:"+c); //[(1,2)]
    
            p.setX(100);
            System.out.println("p:"+p); //(100,2)
            System.out.println("c:"+c); //[(100,2)]
        }
    }
    
  • 集合重写了Object的toString()方法,格式如下:

     [元素1.toString(), 元素2.toString(), 元素3.toString(), ...]
    
  • add()[Einglish:添加]:向集合中添加一个元素,成功添加则返回true

    public class CollectionDemo {
        public static void main(String[] args) {
            Collection c = new ArrayList();
            c.add("one"); //给集合添加元素
            c.add("two");
            c.add("three");
            c.add("four");
            c.add("five");
            System.out.println(c); //Collection中重写了Object的toString()方法
    
  • size()[Einglish:大小,数量]:返回当前集合的元素个数

    		int size = c.size(); //获取集合的元素个数
    		System.out.println("size:"+size); //5
    
  • isEmpty()[Einglish:是空的]:判断当前集合是否为空集,当且仅当size()为=0时返回true

    		boolean isEmpty = c.isEmpty(); //判断集合是否为空集(size为0表示为空集)
    		System.out.println("是否为空集:"+isEmpty); //false
    
  • clear()[Einglish:清理]:清空集合

    		c.clear(); //清空集合
    		System.out.println("集合已清空");
    		System.out.println(c); //[]
    		System.out.println("size:"+c.size()); //0
    		System.out.println("是否为空集:"+c.isEmpty()); //true
    	}
    }
    
  • contains()[Einglish:包含]:判断集合是否包含给定元素

    boolean contains(集合中的元素类型)

    判断依据:给定元素是否与集合元素存在equals比较为true的情况

    public class CollectionDemo {
        public static void main(String[] args) {
            Collection c = new ArrayList();
            c.add(new Point(1,2));
            c.add(new Point(3,4));
            c.add(new Point(5,6));
            c.add(new Point(7,8));
            c.add(new Point(9,0));
            c.add(new Point(1,2));
            System.out.println(c);
            
            Point p = new Point(1,2);
            boolean contains = c.contains(p);
            System.out.println("是否包含:"+contains); //true
    
  • remove()[Einglish:删除]:从集合中删除给定元素,成功删除则返回truemap

    boolean remove(集合中的元素类型)

    从集合中删除与给定元素equals比较为true的元素,若存在重复元素则只删除一次

    		c.remove(p);
    		System.out.println(c);
    	}
    }
    
  • addAll():将参数组定集合中的元素添加到当前集合中,添加后当前集合发生改变则返回true

    boolean addAll(集合中的元素类型)

    public class CollectionDemo2 {
        public static void main(String[] args) {
            Collection c1 = new ArrayList();
            c1.add("java");
            c1.add("c++");
            c1.add(".net");
            System.out.println("c1: "+c1); //c1: [java, c++, .net]
    
            Collection c2 = new ArrayList();
            c2.add("android");
            c2.add("ios");
            c2.add("java");
            System.out.println("c2: "+c2); //c2: [android, ios, java]
    
            c1.addAll(c2); //将c2添加到c1中
            System.out.println("c1: "+c1); //c1: [java, c++, .net, android, ios, java]
            System.out.println("c2: "+c2); //c2: [android, ios, java]
    
  • containsAll():判断当前集合中是否包含参数集合中的所有元素

    boolean containsAll(Collection c)

    		Collection c3 = new ArrayList();
    		c3.add("c++");
    		c3.add("android");
    		c3.add("php");
    		System.out.println("c3: "+c3); //c3: [c++, android, php]
    
    		boolean contains = c1.containsAll(c3); //判断c1中是否包含c3
    		System.out.println("包含所有: "+contains);
    
  • retainAll():取交集

    取交集,c1中仅保留c1与c3的共有元素,c3不变

    		c1.retainAll(c3);
    		System.out.println("c1: "+c1); //c1: [c++, android]
    		System.out.println("c3: "+c3); //c3: [c++, android, php]
    
  • removeAll():删交集

    删交集,将c1中与c3共有的元素删除,c3不变

    		c1.removeAll(c3);
    		System.out.println("c1: "+c1); //c1: [java, .net, ios, java]
    		System.out.println("c3: "+c3); //c3: [c++, android, php]
    	}
    }
    

集合Iterator遍历

  • 迭代器的作用:遍历集合的过程中安全的移除集合中的元素
  • Collection接口提供了统一的遍历集合的方式

    迭代器模式:通过iterator()方法可以获取一个用于遍历当前集合元素的迭代器(Iterator接口)。

  • java.util.Iterator接口:定义了迭代器遍历集合的相关操作,不同的集合都实现了用于遍历自身元素的迭代器实现类,但我们无需记住它们的名字,从多态的角度把它们看成Iterator即可。

  • 使用Iterator遍历要是删除元素

    不可以使用集合的引用调用remove()方法,只能使用迭代器Iterator的引用调用remove()删除元素

  • 迭代器遍历遵循的步骤为:问(hasNext())、取(next())、删(remove()),但删除并不是必要操作.

  • **注意:**当集合结构改变(增、删元素)后,需要重新获取集合的迭代器对象,否则遍历时会报异常,但是使用迭代器的remove方法来删除元素时可以不用重新获取迭代器对象。

  • 迭代器也可以指定泛型

    • 集合中的元素类型一样的时候,就不需要指定泛型

    • 集合中的元素类型不一样的时候,使用迭代器就要指定泛型,要不会报错.这种情况下的泛型就相当于过滤器,只会遍历集合中指定泛型的元素

  •   public class IteratorDemo {
          public static void main(String[] args) {
              Collection c = new ArrayList();
              c.add("one");
              c.add("#");
              c.add("two");
              c.add("#");
              c.add("three");
              c.add("#");
              c.add("four");
              c.add("#");
              c.add("five");
              System.out.println(c); //[one, #, tow, #, three, #, four, #, five]
    
  • 迭代器的常用方法:

    • 1)boolean hasNext()-------问

      询问集合是否还有"下一个"元素可供迭代

      • 注意:迭代器默认开始位置是在集合第1个元素之前
      • 无论调用多少次hasNext()方法,迭代器的位置都不会变
    • Object next()-----------取

      迭代器向后移动一个位置来指向集合的下一个元素并将其获取

    • Iterator it = c.iterator(); //获取集合c的迭代器
              while(it.hasNext()){ //若有下一个元素
                  String str = (String)it.next(); //获取下一个元素
                  if("#".equals(str)){ //若str为#号
                      //c.remove(str); //迭代器遍历过程中不能通过集合方法增删元素,否则会报异常
                      it.remove(); //删除next()方法所获取的元素
                  }
                  System.out.println(str);
              }
              System.out.println(c); //输出集合元素
      	}
      }
      

增强for循环/新循环

foreach

  • iter快捷键

    for (AlbumListItemVO item : list) {
        log.debug("{}",item);
    }
    
  • jdk1.5时推出了一个特性:增强型for循环,也称为新循环,让我们使用相同的语法遍历集合和数组。

  • 注意:

    1. 我们不能在foreach中对集合进行元素的增删
    2. 若需要循环移除元素请使用Iterator中的remove()方法
  • 语法:

    for(元素类型 变量名 : 集合或数组){
        循环体
    }
    
  • 遍历String数组

    新循环遍历数组------会被编译器改回普通的for循环

    public class NewForDemo {
        public static void main(String[] args) {
            String[] array = {"one","two","three","four","five"};
            for(int i=0;i<array.length;i++){
                System.out.println(array[i]);
            }
            for(String str : array){
                System.out.println(str);
            }
    
  • 遍历集合

    新循环遍历集合------会被编译器改回迭代器遍历

    		Collection c = new ArrayList();
            c.add("one");
            c.add("two");
            c.add("three");
            c.add("four");
            c.add("five");
            Iterator it = c.iterator();
            while(it.hasNext()){
                String str = (String)it.next();
                System.out.println(str);
            }
            for(Object obj : c){
                String str = (String)obj;
                System.out.println(str);
            }
        }
    }
    

泛型

  • jdk1.5时推出了一个特性:泛型

  • 泛型也称为参数化类型,允许我们在使用一个类时,传入某个类型来规定其内部的属性、方法参数或返回值类型,使得我们使用的时候更加方便。

    • 泛型在集合中被广泛使用,用来指定集合中元素的类型

    • 若不指定泛型的具体类型,则默认为Object。

    • 若指定了泛型的具体类型,在获取泛型的值时,编译器会补充强转操作

    • <?>表示什么类型都可以
      public class GenericDemo {
          public static void main(String[] args) {
              Collection<Point> c = new ArrayList<>();
              c.add(new Point(1,2));
              c.add(new Point(3,4));
              c.add(new Point(5,6));
              c.add(new Point(7,8));
              Iterator<Point> it = c.iterator();
              while(it.hasNext()){
                  Point p = it.next();
                  System.out.println(p);
              }
              for(Point p : c){
                  System.out.println(p);
              }
      
    • 添加元素的元素类型必须与泛型一致

              Collection<String> c = new ArrayList<>();
              c.add("one");
              c.add("two");
              c.add("three");
              c.add("four");
              c.add("five");
              //c.add(123); //编译错误,参数类型违背了集合c所指定的泛型的实际类型String
      
    • 迭代器所指定的泛型应当与其遍历的集合的泛型一致

      指定泛型后,获取元素无需再手动强转

      		Iterator<String> it = c.iterator();
              while(it.hasNext()){
                  String str = it.next(); 
                  System.out.println(str);
              }
              for(String str : c){
                  System.out.println(str);
              }
      	}
      }
      

集合与数组的转换

  • 集合转为数组:Collection接口提供了一个方法toArray(),可以将当前集合转换为一个数组

    String[] toArray()

    一般情况下把参数设置为0

    若参数数组元素个数==集合元素个数,那就正常转换

    若参数数组元素个数<集合元素个数,那就正常转换(按照集合大小给数组)

    若参数数组元素个数>集合元素个数,则正常转换,同时末尾补默认值

    public class CollectionToArrayDemo {
        public static void main(String[] args) {
            Collection<String> c = new ArrayList<>();
            c.add("one");
            c.add("two");
            c.add("three");
            c.add("four");
            c.add("five");
            System.out.println(c); //[one, two, three, four, five]
            String[] array = c.toArray(new String[0]);
            System.out.println(Arrays.toString(array));
        }
    }
    
  • 数组转为集合:Arrays类的静态方法asList()

    asList()方法会返回内部的ArrayList,该ArrayList内部直接引用给定数组array

    • 作用:可以将一个数组转换为一个List集合
    public class ArrayToCollectionDemo {
        public static void main(String[] args) {
            String[] array = {"one","two","three","four","five"};
            System.out.println("array: "+ Arrays.toString(array));
    
            List<String> list = Arrays.asList(array);
            System.out.println("list: "+list);
        }
    }
    
  • 对数组操作后,集合也会做相应的改变

            array[1] = "six";
            System.out.println("array: "+Arrays.toString(array));
            System.out.println("list: "+list);
    
  • 对集合操作后,数组也会做相应的改变

            list.set(2,"seven"); //将下标2的元素修改为seven-----明天详细讲
            System.out.println("array: "+Arrays.toString(array));
            System.out.println("list: "+list);
    
  • 添加元素/删除元素相当于要往数组中加元素/减元素;而数组是定长的,不会自动扩容/缩容的,因此会发生不支持操作的异常

    		list.add("!!!!!"); //运行时发生不支持操作异常
    	}
    }
    

System.out.println("list: "+list);
}
}


* 对数组操作后,集合也会做相应的改变

```java
        array[1] = "six";
        System.out.println("array: "+Arrays.toString(array));
        System.out.println("list: "+list);
  • 对集合操作后,数组也会做相应的改变

            list.set(2,"seven"); //将下标2的元素修改为seven-----明天详细讲
            System.out.println("array: "+Arrays.toString(array));
            System.out.println("list: "+list);
    
  • 添加元素/删除元素相当于要往数组中加元素/减元素;而数组是定长的,不会自动扩容/缩容的,因此会发生不支持操作的异常

    		list.add("!!!!!"); //运行时发生不支持操作异常
    	}
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值