容器

61 阅读6分钟

目前听完了 课程40前四章 内容

  1. Collection
  2. List
  3. LinkedList
  4. HashSet
  5. LinkesHashSet
  6. TreeSet
  7. Map
  8. HashMap

数组,集合都是对多个数据进行存储操作的,简称为容器 这里的存储指的是内存层面的存储,而不是持久层存储(例持久层存储 如.txt,.avi,.jpg,数据库)

Screenshot_2022-11-18-15-46-57-279_com.baidu.netd.jpg 前后端与数据库之间关联方式 Screenshot_2022-11-18-15-52-50-516_com.baidu.netd.jpg

Collection

public class collection {

    public static void main(String[] args) {
        /*
        collection接口常用方法:
        增加 add(E e) addAll(Collection<? extends E> c)
        删除 clear() remove(Object o)
        修改
        查看 iterator() size()
        判断 contains(Object o) equals(Object o) isEmpty()
        == 比较的是地址 equals比较的是内容
         */
        //接口不能创建对象 利用实现类创建对象
        Collection col=new ArrayList();
        //集合特点 只能存放引用数据类型 不能存放基本数据类型
        //基本数据类型自动装箱 对应包装类 int->Integer
        col.add(18);
        col.add(19);
        //对集合遍历
        for (Object o:col){
            System.out.println(o);
        }
        //对集合遍历
        Iterator it=col.iterator();
        while (it.hasNext()){
            //it相当于指针 通过hasNext()来判断是否有下一个元素 有返回true 没有返回false
            System.out.println(it.next());//it.next()输出指针指向对值,指针向后移动一个位置
        }
        System.out.println(col);
        List list=Arrays.asList(new Integer[]{11,23});
        col.addAll(list);
        boolean isremove=col.remove(15);
        col.clear();
    }
}

List

public class list {
    public static void main(String[] args) {
        /*
        List接口中常用方法:
        增加 add(int index,E element)
        删除 remove(int index) remove(Object o)
        修改 set(int nde,E element)
        查看 get(int index)
        判断
         */
        //接口不能创建对象,可以用接口实现类创建对象,可以用接口对实现类创建对象,
        //把创建后的对象作为接口创建的对象
        List list=new ArrayList();
        list.add(1);
        list.add(14);
        list.add(2);
        list.add(3,66);
        list.set(2,77);
        //在集合中存入的是Integer类型数据,调用remove调用的是remove(int index)
        System.out.println(list);
        Object o=list.get(0);
        //遍历1
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        //遍历2
        for(Object a:list){
            System.out.println(a);
        }
        //遍历3
        Iterator it=list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        ArrayList d=new ArrayList();
        d.add(13);
    }
    
}

泛型

一般在使用时基本上往集合中存入的都是相同类型的数据,便于管理,所以现在什么引用数据类型都可以存入集合,不方便 泛型相当于标签,集合容器类在设计阶段/声明阶段不能确定这个容器到底是寄存的是什么类型的对象,所以在JDK1.5之前,只能把元素类型设计为Object。JDK1.5之后,使用泛型来解决。因为这个时候除了元素的类型,不确定其他的部分是确定的,例如关于这个元素如何保存如何管理等是确定的。Collection,List,ArrayList就是这个就是类型参数,即泛型。加入泛型的优点,在编译时期就会对类型进行检查。
泛型只是对编译器进行了限制,比如ArrayLista=new ArrayList();只是在编译时限制了在a中只能加Integer类型数据,但是在底层看,a是可以加Object类型数据的。

ArrayList<Integer>a=new ArrayList<Integer>();
a.add(1);
//JDK1.7后可以写为
ArrayList<Integer>b=new ArrayList<>();

泛型类实例化

public class test<E> {
    int age;
    E sex;//sex的类型与test相同
    public void a(E n){

    }
    public void b(E[] m){

    }
}
//指定父类泛型 子类就不需要再指定泛型
class subtest extends test<Integer>{
    
}
//如果父类不指定泛型,子类也会变成一个泛型类
class subtest2<E> extends test<E>{
    
}
class Test{
    public static void main(String[] args) {
        //1.实例化的时候不指定泛型,那么认为泛型为Object
        test A=new test();
        A.a("123");
        A.a(123);
        //2.实例化指定泛型 推荐
        test<String> B=new test<>();
        B.a("123");
        B.b(new String[]{"a","b","c"});
        
        subtest s=new subtest();
        s.a(1);
    }
}

定义的参数类型可以是多个
泛型可以使用多个字母
不可以 A[] i=new A[10];
泛型类的静态方法不能使用类的泛型

//泛型可以使用多个字母
public class multi<A,B,C>{
    A age;
    B name;
    C sex;
    public void a(A m,B n,C x){
        //不可以 A[] i=new A[10];
        A[] i=(A[])new Object[10];
    }
    //泛型类的静态方法不能使用类的泛型
    /*
    因为 static是先于对象加载的,等创建完对象,才会给泛型定义,
    而在泛型静态方法中如果已经使用了还未加载的泛型定义 则会报错
    public static int c(A a){
     */
    }

泛型方法

泛型方法不是带泛型的方法,而是这个方法的泛型的参数类型和当前的类的泛型无关

public class multi<A,B,C>{
    //不是泛型
    public void t(A a){
    }
    //是泛型
    public <T> void b(T t){
    }
}

A和B是子类父类关系,但是G和G不存在继承关系,是并列关系,因为在编译的时候只允许输入A和B类型数据,但是在底层都是Object类型

Object obj=new Object();
String s=new String();
obj=s;//多态
List<Object>l1=new ArrayList<>();
List<String>s1=new ArrayList<>();

在没有通配符的时候:
下面的a方法相当于方法的重复定义,报错

public void a(List<?> list){
    //遍历类型用Object接收,不用?接收
    for(Object o:list){
    }
    //只能写入null,因为不知道对象赋给?什么类型数据
    list.add(null);
    //数据读取操作
    Object s=list.get(0);
}
public static void main(String[] args) {
    List<Object>list1=new ArrayList<>();
    List<String>list2=new ArrayList<>();
 List<?>list=null;
 list=list1;
 list=list2;
}

泛型受限

泛型上限
泛型下限

class Test{
    public void a(List<?> list){
    }
    public static void main(String[] args) {
        List<Object>a=new ArrayList<>();
        List<person>b=new ArrayList<>();
        //stu是person子类
        List<stu>c=new ArrayList<>();
        //泛型受限:泛型上限是person
        List<? extends person>list1=null;
        list1=b;
        list1=c;
        //泛型受限:泛型下限是person
        List<? super person>list2=null;
        list2=a;
        list2=b;
    }
}

LinkedList

poll和remove区别:
当LinkedList里面数据,poll不会报错remove会报错

public class linkedList {
    /*
    LinkedList常用方法
    增加 addFirst(E e) addList(E e) offer(E e) offerFirst(E e)
    删除 poll() pollFirst() removeFirst() removeLast()
    修改
    查看 element() getFirst() getLast() indexOf(Object o)
    LastIndexOf(Object o)
    peek() peekFirst() peekLast()
    清空 clear()
     */
    public static void main(String[] args) {
        LinkedList<Integer>list=new LinkedList<>();
        list.add(123);
        list.add(234);
        list.addFirst(1);
        //遍历1
        for (int i=0;i<list.size();i++)
            System.out.println(list.get(i));
        //遍历2
                for (Integer i:list)
                    System.out.println(i);
        //遍历3
        for (Iterator<Integer>it=list.iterator();it.hasNext();)
            System.out.println(it.next());
        System.out.println(list.getFirst());
        list.poll();
        System.out.println(list.getLast());
        list.clear();
        //区别
        System.out.println(list.pollLast());//null
        //System.out.println(list.removeLast());//报错
    }
}

LinkedList简要原理图
底层是个双向链表 Screenshot_2022-11-20-14-53-26-571_com.baidu.netd.jpg

ArrayList,List,Collection,Iterable,Iterator之间的关系

Screenshot_2022-11-20-16-59-54-592_com.baidu.netd.jpg

listIterator

报错

while (it.hasNext()){
    //报错,原因是 list和it同时操作list
    //it.next()会操作list list.add操作list
    if("1".equals(it.next())){
        list.add("ni hao");
    }
}

由于上述报错,引入listIterator,迭代和add都是靠listIterator完成的

public static void main(String[] args) {
    List list=new ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add(3,"5");
   ListIterator<String> it=list.listIterator();
    while (it.hasNext()){
        if("1".equals(it.next())){
            it.add("ni hao");
        }
    }
    System.out.println(it.hasNext());//返回false 下面没有元素了
    System.out.println(it.hasPrevious());//true 上面有元素
    //逆向遍历
    while (it.hasPrevious())
        System.out.println(it.previous());//5 3 2 ni hao 1
}

HashSet

放入自定义引用数据类型,不满足唯一,无序的特点,原因是:在自定义引用数据类型中没有重写hashCode和equals方法 HashCode原理图:
在集合中存入数据,调用对应的hashCode方法计算哈希值,通过哈希值和一个表达式计算在数组中存放的位置,如果存放的位置已经有值了且与该值不同,链接到后,如果已经存在,不链接 29.HashSet的简要原理_ev20221120-204245.png

LinkedHashSet

在Hashset基础上,多了一个总的链表,这个总链表将放入的元素串在一起

TreeSet

唯一,升序
底层是二叉树

33.TreeSet的使用及原理_ev20221204-112824.png

自定义类需要实现比较器  

通过内部比较器来比较

接口文件

package java.lang;
import java.util.*;
    public int compareTo(T o);
}

stu类

public class stu implements Comparable<stu>{
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return "stu{" +
                "age=" + age +
                ", name='" + name + ''' +
                '}';
    }
    private int age;
    private String name;
    stu(int age,String name){
        this.age=age;
        this.name=name;
    }
    public int compareTo(stu o){
        return this.getAge()-o.getAge();
    }
}

测试类:

import java.util.TreeSet;
public class test1 {
    public static void main(String[] args) {
        TreeSet<stu>t=new TreeSet<>();
        t.add(new stu(10,"d"));
        t.add(new stu(11,"DA"));
        System.out.println(t);
        System.out.println(t.size());
    }
}
### 通过外部比较器来比较 

37.TreeMap的使用_ev20221204-165349.png

Map

Map无序唯一

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class map {
    /*
    增加 put(K key V value)
    删除 clear() remove(Object key()
    查看 entrySet() get(Object key) keySet() size() values()
    判断 containsKEy(Object key) containsValue(Object value)
    equals(Object o) isEmpty()
     */
    public static void main(String[] args) {
        Map<Integer,String>mp=new HashMap<>();
        mp.put(123,"q");
        mp.put(234,"hi");
        System.out.println(mp.containsKey(123));
        System.out.println(mp.containsValue("hi"));
        System.out.println(mp.get(123));

        Set<Integer>set=mp.keySet();//对集合中对set遍历
        for (Integer i:set){
            System.out.println(i);
        }
        Collection<String>value=mp.values();
        for (String s:value){
            System.out.println(s);
        }
        Set<Map.Entry<Integer,String>>entries=mp.entrySet();
        for (Map.Entry<Integer,String> e:entries){
            System.out.println(e.getKey()+e.getValue());
        }
    }
}

37.TreeMap的使用_ev20221204-231537.png

37.TreeMap的使用_ev20221204-231942.png

# Map  

增删查改

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class map {
    /*
    增加 put(K key V value)
    删除 clear() remove(Object key()
    查看 entrySet() get(Object key) keySet() size() values()
    判断 containsKEy(Object key) containsValue(Object value)
    equals(Object o) isEmpty()
     */
    public static void main(String[] args) {
        Map<Integer,String>mp=new HashMap<>();
        mp.put(123,"q");
        mp.put(234,"hi");
        System.out.println(mp.containsKey(123));
        System.out.println(mp.containsValue("hi"));
        System.out.println(mp.get(123));

        Set<Integer>set=mp.keySet();//对集合中对set遍历
        for (Integer i:set){
            System.out.println(i);
        }
        Collection<String>value=mp.values();
        for (String s:value){
            System.out.println(s);
        }
        Set<Map.Entry<Integer,String>>entries=mp.entrySet();
        for (Map.Entry<Integer,String> e:entries){
            System.out.println(e.getKey()+e.getValue());
        }
    }
}

内部比较器

public class stu implements Comparable<stu>{
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return "stu{" +
                "age=" + age +
                ", name='" + name + ''' +
                '}';
    }
    private int age;
    private String name;
    stu(int age,String name){
        this.age=age;
        this.name=name;
    }
    public int compareTo(stu o){
        return this.getName().compareTo(o.getName());
    }
}
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
public class test1 {
    public static void main(String[] args) {
        Map<stu,Integer>mp=new TreeMap<>();
        mp.put(new stu(18,"wxy"),1);
        mp.put(new stu(19,"wbb"),2);
        mp.put(new stu(17,"dfg"),1);
        System.out.println(mp);
    }
}

外部比较器

public class stu{
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return "stu{" +
                "age=" + age +
                ", name='" + name + ''' +
                '}';
    }
    private int age;
    private String name;
    stu(int age,String name){
        this.age=age;
        this.name=name;
    }
}
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
public class test1 {
    public static void main(String[] args) {
        Map<stu,Integer>mp=new TreeMap<>(new Comparator<stu>() {
            @Override
            public int compare(stu o1, stu o2) {
                return (((Integer)(o1.getAge())).compareTo((Integer)(o2.getAge())));
            }
        });
        mp.put(new stu(18,"wxy"),1);
        mp.put(new stu(19,"wbb"),2);
        mp.put(new stu(17,"dfg"),1);
        System.out.println(mp);
    }
}

HashMap

原理 38.HashMap的原理简单介绍_ev20221205-100725.png 1.调用hashCode方法,算出哈希值
2.将哈希值带入某算法计算出在数组中的位置 3.当发生哈希冲突,使用头插法把新节点插到相同哈希值元素的前面