API_Day06_集合框架(Collection)01


在这里插入图片描述

在这里插入图片描述

Collection 是一个接口(interface),他是一个用来存放对象的数据结构,其中长度可变,而且集合中可以存放不同类型的对象,并提供了一系列操作此对象的方法。
分成对外的接口,接口的实现,以及集合框架的算法。

集合和数组一样,都是用来存储数据的(多个数据);

1. 集合与数组存储数据概述:
集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)

2. 数组存储的特点:

一旦初始化以后,其长度就确定了。
数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。

  •   比如:String[] arr;int[] arr1;Object[] arr2;
    

3. 数组存储的弊端:

  •  > 一旦初始化以后,其长度就不可修改。
    
  •  > 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
    
  •  > 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
    
  •  > 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
    
  •  >数组按照下标遍历,适合查询
    

4. 集合存储的优点:

  • 解决数组存储数据方面的弊端。

  • 可变长度,遍历方式丰富

  • 适合增删查询。

集合的继承结构

在这里插入图片描述

把共性的东西向上抽取,最终形成容器的继承体系结构。(Abstract)

一、Collection 的子接口

1.1 List接口:存储数据有序,可以重复

1.1.1 List接口的实现类:

ArrayList类 (常用):
LinkedList类:
vector类:

1.1.2常用方法

  • boolean add(E e)添加元素

  • boolean addAll(Collection<? extends E> c)把小集合添加到大集合中

  • boolean contains(Object o)如果此collection 包含指定的元素,则返回true。

  • boolean isEmpty() 如果此collection 不包含元素,则返回true

  • boolean remove(Object o) 从此collection 中移除指定元素的单个实例,如果存在的话 。

  • int size() 返回此collection 中元素数(集合的长度)

  • Object[] toArray() 返回包含此collection 中所有元素的数组,(集合转成数组)

  • removeAll(Collection col):差集,从当前集合中移除col中的所有元素

  • retainsAll(Collection col):交集,获取当前集合和col的交集,并返回给当前集合。

  • equals(Object obj):要想返回true,需要当前集合和形参集合的元素都相同

  • hashCode():返回当前对象的哈希值

遍历集合元素的方式

方式一:迭代器Iterator
方式二:增强for循环
方式三:普通循环

迭代器Iterator

遍历集合的方式,Iterator 只是遍历集合,不是容器本身不装东西。

  • Iterator iterator() 返回此collection的元素上进行迭代的迭代器(遍历元素)
    常用方法

  • boolean hasNext()//通过迭代器判断集合里是否有元素

  • E next();
    代码实现:
    泛型 常用来和集合对像一同使用。
    本质上就是编译器为了提供更好的可读性而提供的一种小手段。
    通过泛型的语法定义来约束集合元素的类型,进行安全检查,把错误显示在编译期
    Collection col = new ArrayList();

遍历集合的方式
方式一:通过迭代器Iterator iterator(),— 返回迭代器Iterator,专门用来迭代集合里的元素

//遍历集合
        while (it.hasNext()){//hadNext()判断有元素嘛,有的话就返回true.
            Integer in = it.next();//next()获取元素。
            System.out.print(in+" ");
        }

方式二:增强for循环:for(数据类型 变量名 :容器(集合)){}

   //方式二:增强for循环:for(数据类型 变量名 :容器(集合)){}
        for (Integer in : col){
            System.out.println(in);
        }
package day05Collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**
 * @author yyc
 */
public class CollectionTest1 {
    public static void main(String[] args) {
        //<E>泛型 常用来和集合对像一同使用。
        // 本质上就是编译器为了提供更好的可读性而提供的一种小手段。
        // 通过泛型的语法定义来约束集合元素的类型,进行安全检查,把错误显示在编译期
        //1.创建集合对象,泛型约束里面的类型是引用类型,不能是基本类型
        Collection<Integer> col = new ArrayList<>();//<>前面使用的了泛型。前后保持一致
        //col.add("aaa");报错
        col.add(23);
        //2.常用方法
        //①集合添加元素常用add()
        col.add(45);
        col.add(1);
        System.out.println(col);
        //col.clear();清空集合
        System.out.println(col);
        System.out.println(col.contains(5));//判断此集合中是否包含指定数,true.
        System.out.println(col.equals(23));//判断集合是否与23是否相等
        System.out.println(col.hashCode());//获取col的哈希值,53290
        System.out.println(col.remove(23));//从集合col中移除23
        System.out.println(col);
        System.out.println(col.isEmpty());//判断集合四否为空
        System.out.println(col.size());//获取集合的长度
        Object[] os = col.toArray();//集合转数组
        System.out.println(Arrays.toString(os));//[45, 1]

        Collection<Integer> col2 = new ArrayList<>();
        col2.add(67);
        col2.add(68);
        col2.add(69);
        col.addAll(col2);//向集合col中添加集合col2
        System.out.println(col);
        System.out.println(col.size());
        System.out.println(col.containsAll(col2));//判断col中是否包含col2
        System.out.println(col2.retainAll(col));//求交集(col2 和 col中相同的元素)
        //获取集合中的元素
        //方式一:通过迭代器Iterator<E> iterator(),--- 返回迭代器Iterator,专门用来迭代集合里的元素
        Iterator<Integer> it = col.iterator();//通过集合的迭代器方法获取迭代器引用,迭代器不是容器
       //遍历集合
        while (it.hasNext()){//hadNext()判断有元素嘛,有的话就返回true.
            Integer in = it.next();//next()获取元素。
            System.out.print(in+" ");
        }
        System.out.println();
        //方式二:增强for循环:for(数据类型 变量名 :容器(集合)){}
        for (Integer in : col){
            System.out.println(in);
        }

    }
}

collections 工具类

概述:专门给collection 集合提供方法的.Collections 是Collection的实现类

  • static boolean addAll(Collection <? super T>c, T …elements) 将所有指定元素添加到指定collection中。

  • static T max(Collection<? extends T> col) 根据其元素的 自然顺序返回给定集合的最大元素

  • static T min(Collection<? extends T> coll, Comparator<? super T> comp) 其元素的 自然顺序返回给定集合的最小元素。

  • static void sort(List list, Comparator<? super T> c) 根据指定比较器产生的顺序对指定列表进行排序。

  • static void reverse(List<?> list) 反转指定列表中元素的顺序。

  • static void swap(List<?> list, int i, int j)在指定列表的指定位置处交换元素

package day05Collection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author yyc
 */
/*
* 测试Collection 的工具类Collections
* */
public class Collections_Test {
    public static void main(String[] args){
        //1.创建List集合并添加元素
        List<Integer> list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println(list);
        //一次性向集合中添加元素。
        Collections.addAll(list,15,23,54,65,34);
        System.out.println(list);
        System.out.println(Collections.max(list));//获取最大值。
        System.out.println(Collections.min(list));//获取最小值

        //reverse(List list)反转
        Collections.reverse(list);
        System.out.println(list);

        //给集合进行自然排序
        Collections.sort(list);
        System.out.println(list);//给list集合记性自然排序
        
        Collections.swap(list,0,2);
        //给list集合的下标0和下标2的元素交换位置
        System.out.println(list);
    }
}

2.2List接口

概述:是有序的Collection ,是Collection接口的子接口,可以使用Collection的所有方法,除此之外还做了很多扩展方法,此接口的用户可以对列表中的每个元素的插入位置进行精确的控制,用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的 元素。

特点

  • 元素有序

  • 允许存放重复元素

  • 元素有索引

  • 可以存放null

常用方法

  • ListIterator listIterator() 返回此列表元素的列表迭代器(按适当顺序)。

  • ListIterator listIterator(int index) 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

  • boolean add(E e) 向列表的尾部添加指定的元素(可选操作)。

  • E set(int index, E element)
    用指定元素替换列表中指定位置的元素(可选操作)。

  • List subList(int fromIndex, int toIndex)
    返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

public static void main(String[] args) {
        List<String> list = new ArrayList();
        list.add("超级英雄");
        list.add("开心超人");
        list.add("小猪佩奇");
        list.add("开心超人");
        list.add(null);
        list.add("冰雪奇缘");
        list.add("齐天大圣孙悟空");
        list.add(null);
        System.out.println(list);

运行结果
在这里插入图片描述

List 特点:元素有序+元素可重复+可以存放多个null +有下标*

package day05Collection.ListTest;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/**
 * @author yyc
 */
public class ListDeom {
    public static void main(String[] args) {
        List<String> list = new ArrayList();
        list.add("超级英雄");
        list.add("开心超人");
        list.add("小猪佩奇");
        list.add("开心超人");
        list.add(null);
        list.add("冰雪奇缘");
        list.add("齐天大圣孙悟空");
        list.add(null);
        System.out.println(list);
        method2(list);
    }
    //练习List接口特有的方法
    public static void method2(List<String> list){
        list.add(4,"绿巨人");//在指定索引出,添加指定元素
        System.out.println(list.get(5));//null ,根据下标获取元素
        System.out.println(list.indexOf("开心超人"));//获取开心超人第一次出现的索引
        System.out.println(list.lastIndexOf("开心超人"));//获取null最后一次出现的索引
        System.out.println(list.remove(3));//根据下标移除,返回移除位置的值。
        System.out.println(list.set(2,"灭霸"));//把2下标处的元素换成灭霸
        List<String> list2 = list.subList(2,5);//截取list从2开始到5结束[2,5)
        System.out.println(list);
        System.out.println(list2);
        //迭代List集合 。方式一:Iterator<E> iterator 继承自-Collection接口
        Iterator<String> it = list.iterator();
        //遍历迭代器对象
        while (it.hasNext()){
            String str = it.next();
            System.out.print(str +"---");
        }
        System.out.println();
        //迭代List集合 方式二:ListIterator<E> listIterator() -- List接口特有的
        ListIterator<String> it2 = list.listIterator();
       //遍历列表迭代器
        while (it2.hasNext()){
            String str = it2.next();
            System.out.print(str+"~~~");
        }
        //逆向遍历之前必须顺序遍历
        System.out.println();
        while (it2.hasPrevious()){//hasPrevious()是逆向遍历
            String str = it2.previous();
            System.out.print(str+"---");
        }
        System.out.println();
        //方式三:由于List集合有下标,可以按照下标遍历
        for(int i = 0; i < list.size(); i++){
            String  str = list.get(i);//根据指定下标获取元素
            System.out.print(str+"\\\\");
        }
        System.out.println();
        //方式四:增强for循环
        for (String s : list){
            System.out.print(s +"**");
        }
    }
}

  • void add(int index, E element) 在列表的指定位置插入指定元素(可选操作)。

  • boolean addAll(Collection<? extends E> c)
    添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。

  • boolean addAll(int index, Collection<? extends E> c)
    将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。

  • void clear()
    从列表中移除所有元素(可选操作)。

  • E get(int index)
    返回列表中指定位置的元素。

  • int indexOf(Object o)
    返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

  • E set(int index, E element)
    用指定元素替换列表中指定位置的元素(可选操作)。

  • List subList(int fromIndex, int toIndex)
    返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图

  • E remove(int index)
    移除列表中指定位置的元素(可选操作)。

  • boolean remove(Object o)
    从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。

package day05Collection.ListTest;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

/**
 * @author yyc
 */
//测试删除集合List集合中200这个元素
//添加元素100,200,300,Integer类型。删除200元素而不是删除下标为200的元素;
public class ListDeom2 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(100);
        list.add(200);
        list.add(200);
        list.add(300);
        list.add(200);
        list.add(200);
        System.out.println(list);
        //方式一:删除200
     /*  for(int i = 0; i < list.size(); i++){
          if(i == list.indexOf(200)){//找到200的下标,然后删除该位置的元素。
              list.remove(i);
          }
       }
        System.out.println(list);*/

        //解决方案:不能传入一个基本类型的变量值,默认当成下标
        //System.out.println(list.remove((Integer)200));//只能删除第一个200
        //System.out.println(list.remove(Integer.valueOf(200)));//只能删除第一个200,自动装装箱
        // System.out.println(list);
        ListIterator it = list.listIterator();
        while (it.hasNext()){
            Integer i = (Integer) it.next();
            if (i == 200){
                it.remove();
            }
        }
        /*//跳着删除200
        for (int i = 0; i < list.size(); i++){
            if (list.get(i) == 200){
                list.remove(i);
            }
        }*/
        System.out.println(list);
    }
}

ArrayList实现类

概述

  • 存放与java.util包下,是 List 集合的实现类

  • 内部是用数组存放的数据的,封装了数组的操作,每个元素都有下标

  • 内部数组默认初始容量为10, 如果不够会以1.5倍容量增长

  • 查询快,增删数据效率会变低

ArrayList 扩容

ArrayList 相当于没指定initalCapacity时就会使用延迟分配对象数组空间,当第一次插入元素时才分配10(默认)个对象空间,假如有20个元素需要添加,那么会在第一次的时候,将ArrayList的容量变为10,之后扩容按照1.5倍增长,就是说当添加第11个元素的时候,ArrayList会继续扩容变为101.5 = 15,当添加第16个元素的时候,继续扩容为151.5 = 22个空间;

  • jdk1.6是创建了一个ArrayList 对象时,直接创建了一个容量为10的数组。

  • jdk1.8是创建了一个ArrayList对象时,创建了一个空数组。是为了优化内存。first element is added 才会扩容。

  • ArrayList arrayList = new ArrayList();//容量为0.
    arrayList.add(2);//当且仅当添加第一个元素时数组才扩容至第一次容量为10,数组默认容量是10 ,当超过10 个元素时,底层会自动扩容,
    * >扩容方式:int newCapacity = oldCapacity + (oldCapacity >> 1)就是旧容量的1.5倍

package day05Collection.ListTest;

import java.util.ArrayList;

/**
 * @author yyc
 */
public class ArrayListDemo {
    public static void main(String[] args) {
        //jdk1.6是创建了一个ArrayList 对象时,直接创建了一个容量为10的数组。
        //jdk1.8是创建了一个ArrayList对象时,创建了一个空数组。是为了优化内存。first element is added 才会扩容。
        ArrayList arrayList = new ArrayList();//容量为0.
        arrayList.add(2);//当且仅当添加第一个元素时数组才扩容至第一次容量为10,数组默认容量是10 ,当超过10 个元素时,底层会自动扩容,
        //扩容方式:int newCapacity = oldCapacity + (oldCapacity >> 1)
        //就是旧容量的1.5倍


    }
}

1.2 Set接口:存储数据无序,不可存放重复值

Set:存放无序的、不可重复的数据

以HashSet为例说明:
1.无序性:不等于随机性.存储的数据在底层数组中并非按照数组索引的顺序添加,而是按照数组的哈希值
2.不可重复性:保证添加的元素按照equals()方法判断时,不能返回true ,即,相同元素只能添加一个

1、set 接口中没有额外定义新的方法,使用的都是Collection中声明的方法。
2、要求:向Set中添加的数据,其所在类一定要重写hashCode() 和 equals()方法。
要求:重写的hashCode() 和 equals()尽可能保持一致性:相等的对象必须具有相同的散列码
重写方法的小技巧:对象中用作equals()方法比较的Filed,都应该用来计算hashCode值。

二、添加元素的过程:以HashSet为例:

我们像HashSet中添加元素a, 首先调用元素a所在类的hashCode()方法,计算元素a的哈希值。此哈希值接着通过某种算法计算出在HashSet底层数组中存放位置(即为索引位置),判断数组再此位置上是否已经有元素:
如果此位置上没有其他元素,则元素添加成功—> 情况1
如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值,
如果hash值不同,则元素a添加成功。----> 情况2
如果hash值相同,进而需要调用元素a所在类的equals()方法: equals()返回true,元素添加失败。equals()返回false,元素添加成功。---->情况3

对于添加成功的情况2 和情况3 而言:元素a 与已经存在指定索引位置上数据以链表方式存储。
jdk 7 :元素a放到数组中,指向原来的元素
jdk8:原来的元素在数组中, 指向元素a.

总结:七上八下。

HashSet底层:数组+ 链表

package Set;

import org.junit.Test;

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

/**
 * @author yyc
 */
public class SetTest {
   @Test
    public void test1(){
       Set set = new HashSet();
       set.add(456);
       set.add(123);
       set.add(789);
       set.add(789);//不可重复性,添加无效
       set.add("AA");
       set.add("CC");
       set.add(new String("abc"));
       set.add(new User("张三",12));
       set.add(128);
       set.add(new User("张三",12));
       //遍历set中的元素
       //方式一:迭代器
       Iterator iterator = set.iterator();
       while(iterator.hasNext()){
           System.out.println(iterator.next());
       }
   }
}

结果:

"D:\Program Files\Java\jdk1.8.0_211\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\Program Files\Java\idea2020.2.3\IntelliJ IDEA 2020.2.3\lib\idea_rt.jar=64757:D:\Program Files\Java\idea2020.2.3\IntelliJ IDEA 2020.2.3\bin" -Dfile.encoding=GBK -classpath "D:\Program Files\Java\idea2020.2.3\IntelliJ IDEA 2020.2.3\lib\idea_rt.jar;D:\Program Files\Java\idea2020.2.3\IntelliJ IDEA 2020.2.3\plugins\junit\lib\junit5-rt.jar;D:\Program Files\Java\idea2020.2.3\IntelliJ IDEA 2020.2.3\plugins\junit\lib\junit-rt.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_211\jre\lib\rt.jar;E:\neweclipseworkspace\shangguigu_workspace\classes\production\Collection;E:\neweclipseworkspace\shangguigu_workspace\lib\junit-4.12.jar;E:\neweclipseworkspace\shangguigu_workspace\lib\hamcrest-core-1.3.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 Set.SetTest,test1
AA
CC
128
abc
User{name='张三', age=12}
789
456
User{name='张三', age=12}
123

Process finished with exit code 0

1.2.1 Set接口的实现类

1.2.2 HashSet:作为Set接口的主要实现类,线程不安全的;可以存储Null值

1.2.3 LinkedHashSet类:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序去遍历。

LinkedHashSet的使用:
LinkedHashSet 作为HashSet的子类,在添加数据的同时,每个数据还具有前驱和后继指针,记录此数据前一个数据和后一个数据。
优点:对于频繁的遍历操作,LinkedHashSet效率高于HashSet

1.2.4 TreeSet 类:底层存放 的数据必须是同一个类型,可以按照添加的对象指定属性进行排序。

Collections工具

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值