0
点赞
收藏
分享

微信扫一扫

现代C++新特性——constexpr

陆公子521 2024-04-23 阅读 17

一、引入

 

 二、Collection接口

package com.atguiguday01.a_collection;

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

public class Demo01Collection {
    public static void main(String[] args) {
        /**
         * 格式
         *  Collection<E> 集合名 = new 实现类对象<E>()
         * **/
        Collection<String> collection1 = new ArrayList<>();
        //boolean add(E e) : 将给定的元素添加到当前集合中(我们一般调add时,不用boolean接收,因为add一定会成功)
        collection1.add("刘备");//只要写字符串就会直接添加进去
        collection1.add("刘备");//不用布尔类型去接收,一定能接收,编译时就直接报错了
        collection1.add("关羽");
        collection1.add("张飞");
        collection1.add("诸葛亮");
        collection1.add("庞统");
        System.out.println(collection1);

        System.out.println("=========================");
        /**
         * boolean addAll(Collection<? extends E> c) :将另一个集合元素添加到当前集合中 (集合合并)
         * **/
        Collection<String> collection2 = new ArrayList<>();
        collection2.add("宋江");
        collection2.add("林冲");
        collection2.add("卢俊义");

        collection1.addAll(collection2);

        System.out.println(collection1);

        System.out.println("=========================");
        //void clear():清除集合中所有的元素
        //collection1.clear();
        //System.out.println(collection1);

        System.out.println("=========================");

        //boolean contains(Object o)  :判断当前集合中是否包含指定的元素
        boolean result01 = collection1.contains("刘备");
        System.out.println(result01);

        System.out.println("=========================");

        //boolean isEmpty() : 判断当前集合中是否有元素->判断集合是否为空(指的是元素)

        boolean result02 = collection1.isEmpty();
        System.out.println(result02);

        System.out.println("=========================");

        //boolean remove(Object o):将指定的元素从集合中删除
        collection1.remove("刘备");
        System.out.println(collection1);

        System.out.println("=========================");

        //int size() :返回集合中的元素个数。
        System.out.println(collection1.size());

        System.out.println("=========================");

        //Object[] toArray(): 把集合中的元素,存储到数组中
        Object[] arr = collection1.toArray();
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

    }
}

三、迭代器

1)迭代器的基本使用

public class Demo01Iterator {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("贾宝玉");
        list.add("林黛玉");
        list.add("王熙凤");
        list.add("刘姥姥");
        list.add("探春");
        //获取Iterator接口
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){//如果 有的话获取下一个
            String element = iterator.next();
            System.out.println("element = " + element);
        }
    }
}

注意:在进行迭代的时候,不能连续多次调用next方法,一次2个,第三次不够  

public class Demo02Iterator {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("唐三藏");
        list.add("孙悟空");
        list.add("猪悟能");
        list.add("沙悟净");
        list.add("白龙马");
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
            System.out.println(iterator.next());
        }
    }
}

 

 2)迭代器的迭代过程

 3)迭代器的底层原理使用说明

 

public class Demo03Iterator {
 public static void main(String[] args) {
     HashSet<String> set = new HashSet<>();
     set.add("张三");
     set.add("李四");
     Iterator<String> iterator = set.iterator();
 }
}

 4)并发修改异常

/**出现并发异常的代码**/
public class Demo04Iterator {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("唐僧");
        list.add("孙悟空");
        list.add("猪八戒");
        list.add("沙和尚");

        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String element = iterator.next();
            if ("猪八戒".equals(element)){
                list.add("白龙马");
            }
        }
        System.out.println(list);
    }
}

Iterator<String> iterator = list.iterator();

String element = iterator.next();
=================================================
 private class Itr implements Iterator<E> {
        /*
          expectedModCount:预期操作次数
          modCount:实际操作次数
        */
        int expectedModCount = modCount; 
        public E next() {
            checkForComodification(); 
        }  
     
        final void checkForComodification() {
            if (modCount != expectedModCount)//如果实际操作次数和预期操作次数不相等,抛异常
                throw new ConcurrentModificationException();
        }
public class Demo05Iterator {
 public static void main(String[] args) {
     ArrayList<String> list = new ArrayList<>();
     list.add("唐僧");
     list.add("孙悟空");
     list.add("猪八戒");
     list.add("沙和尚");

     ListIterator<String> iterator = list.listIterator();
     while(iterator.hasNext()){
         String element = iterator.next();
         if ("猪八戒".equals(element)){
             iterator.add("白龙马");
         }
     }
     System.out.println(list);
 }
}

 5)数据结构知识补充

1-为什么需要数据结构

 

 数据的逻辑

 

2-常见的几种数据结构的介绍

 

 

四、List接口

1)List集合下的实现类

2)ArrayList集合使用

/**arraylist基本操作1**/
public class Demo01ArrayList {
    public static void main(String[] args) {
        /**
         格式:ArrayList<泛型> 集合名 = new ArrayList<>()
         * **/
        ArrayList<String> list = new ArrayList<>();
        /**boolean add(E e)  ->将元素添加到集合中->尾部(add方法一定能添加成功的,所以我们不用boolean接收返回值)**/
        System.out.println("初始化后的集合:");
        list.add("张三");//向集合中的末尾添加元素
        list.add("李四");
        list.add("王五");
        list.add("赵六");
        list.add("田七");
        System.out.println(list);//输出初始化后的集合
        System.out.println("============================================");
        System.out.println("在指定位置上添加元素后输出");
        //void add(int index, E element) ->在指定索引位置上添加元素
        list.add(0,"猪八");
        System.out.println("list = " + list);
        //boolean remove(Object o) ->删除指定的元素,删除成功为true,失败为false
        //boolean result01 = list.remove("猪八");
        //System.out.println("result01 = " + result01);看输出的值是否成功删除
        //System.out.println("list = " + list);
        //E remove(int index) -> 删除指定索引位置上的元素,返回的是被删除的那个元素
        System.out.println("============================================");
        System.out.println("删除List上第一个元素");
        String element1 = list.remove(0);
        System.out.println("element1 = " + element1);
        System.out.println("list = " + list);
        //E set(int index, E element) -> 将指定索引位置上的元素,修改成后面的element元素
        System.out.println("============================================");
		String element2 = list.set(0, "曼曼");//返回set修改的元素:“曼曼”
        System.out.println("element2 = " + element2);
        System.out.println("list = " + list);
        //E get(int index) -> 根据索引获取元素
        System.out.println(list.get(0));
        //int size()  -> 获取集合元素个数
        System.out.println(list.size());
    }
}
package com.atguiguday01.c_list;

import java.util.ArrayList;
import java.util.Iterator;
/**
 * 迭代器遍历ArrayList
 *
 * **/
public class Demo02ArrayList {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> list = new ArrayList<>();
        //boolean add(E e)  -> 将元素添加到集合中->尾部(add方法一定能添加成功的,所以我们不用boolean接收返回值)
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("赵六");
        list.add("田七");

        //迭代器创建
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("===================");
        for (int i = 0;i<list.size();i++){
            System.out.println(list.get(i));
        }
		/**
		在集合有索引的情况下,普通for循环遍历快捷键:集合名.fori
		**/
        System.out.println("==================");

        for (int i = 0; i < list.size(); i++) {//根据索引获取元素
            System.out.println(list.get(i));
        }
    }
}

import java.util.ArrayList;
/**
 *List接口_删除时要注意的问题说明
 * **/
public class Demo03ArrayList {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(2);//元素2存到了0索引上

        /*
          remove(2) -> 调用的是remove(int index) -> 按照索引删除元素
          但是是存在第0个位置上的
          解决:
            将2转成包装类
         */
        //list.remove(2);
        list.remove(new Integer(2));
        System.out.println(list);
    }
}

 【ArrayList底层源码分析】

ArrayList<Integer> list = new ArrayList<>();
=============================================
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//已经创建声明了
 transient Object[] elementData;-> ArrayList底层的那个数组

 public ArrayList() {
     this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 }
/**
在源码中,具体过程演示
无参构造源码分析
**/

list.add("abc");
=============================================
public boolean add(E e) { -> abc
    ensureCapacityInternal(size + 1);  // Increments modCount!!
} 
//size还是个成员变量,记录元素个数,如果有元素就加1


private void ensureCapacityInternal(int minCapacity -> 1) {//计算容量
    ensureExplicitCapacity(calculateCapacity(elementData->空数组, minCapacity->1));//接收下面返回的方法10
}
//  先传参数,数组一开始时空的,然后传进下面的方法
// ensureExplicitCapacity(calculateCapacity(10));


private static int calculateCapacity(Object[] elementData->空数组, int minCapacity->1) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//相等
        return Math.max(DEFAULT_CAPACITY, minCapacity->1); -> 返回的是10
    }
    return minCapacity;
}

private void ensureExplicitCapacity(int minCapacity->10) {
    modCount++;//实际操作次数加1 
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity->10);
}

private void grow(int minCapacity->10) {
    // overflow-conscious code
    int oldCapacity = elementData.length;//获取数组的老的容量 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);//计算数组新的容量 -> 0
    if (newCapacity - minCapacity < 0)//比较新旧数组容量
        newCapacity = minCapacity;//newCapacity = 10
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:

    //elementData = Arrays.copyOf(老数组,10)  老数组扩容为10 然后会产生一个新数组,赋给 elementData
    elementData = Arrays.copyOf(elementData, newCapacity);
}

/**
下面是有参构造源码分析
**/

ArrayList<String> list2 = new ArrayList<>(10);
=============================================
public ArrayList(int initialCapacity->10) {
    if (initialCapacity > 0) {//小于0 就直接甩异常了
        this.elementData = new Object[initialCapacity];//直接创建数组,长度为指定容量
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}   

 五、List 的接口 LinkedList

1)LinkedList常用类实现

package com.atguiguday01.c_list;
/**常用方法介绍,代码演示**/
import java.util.Iterator;
import java.util.LinkedList;

public class Demo05LinkedList {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("虹猫蓝兔七侠传");//直接添加元素到第0个位置
        list.add("海绵宝宝");
        list.add("天线宝宝");
        list.add("花园宝宝");
        list.add("托马斯小火车");
        list.add("数码宝贝");
        list.add("神奇宝贝");
        list.add("游戏王");
        list.add("灌篮高手");
        list.add("火影忍者");
        System.out.println("输出添加完元素后的集合");
        System.out.println(list);
        //- public void addFirst(E e):将指定元素插入此列表的开头。
        System.out.println("=====================================================================================");
        System.out.println("\n"+"输出将指定元素:网球王子 插入此列表的开头");
        list.addFirst("网球王子");
        System.out.println(list);
        //- public void addLast(E e):将指定元素添加到此列表的结尾。
        System.out.println("=====================================================================================");
        System.out.println("\n"+"输出将指定元素  七龙珠 插入此列表的末尾");
        list.addLast("七龙珠");
        System.out.println(list);
        //- public E getFirst():返回此列表的第一个元素。
        System.out.println("=====================================================================================");
        System.out.println("\n"+"输出这个列表的第一个元素");
        System.out.println(list.getFirst());
        //- public E getLast():返回此列表的最后一个元素。
        System.out.println("=====================================================================================");
        System.out.println("\n"+"输出这个列表的最后一个元素");
        System.out.println(list.getLast());
        //- public E removeFirst():移除并返回此列表的第一个元素。
        System.out.println("=====================================================================================");
        System.out.println("\n"+"删掉列表第一个元素,并返回删除的元素");
        System.out.println(list.removeFirst());
        System.out.println(list);
        //- public E removeLast():移除并返回此列表的最后一个元素。
        System.out.println("=====================================================================================");
        System.out.println("\n"+"删掉列表最后一个元素   七龙珠   ,并返回删除的元素");
        System.out.println(list.removeLast());
        System.out.println(list);
        //- public boolean isEmpty():如果列表不包含元素,则返回true。
        System.out.println("=====================================================================================");
        System.out.println("\n"+"如果列表不包含元素,就返回真值true");
        System.out.println(list.isEmpty());

        System.out.println("===================================");
        //用迭代器去遍历
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //用for循环去遍历
        System.out.println("===================================");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

 【了解】

public class Demo06LinkedList {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("虹猫蓝兔七侠传");
        list.add("海绵宝宝");
        list.add("天线宝宝");
        list.add("花园宝宝");
        //public E pop():从此列表所表示的堆栈处弹出一个元素。----》弹出第一个元素
        list.pop();
        System.out.println(list);
        //public void push(E e):将元素推入此列表所表示的堆栈。
        list.push("曼曼");
        System.out.println(list);
    }
}

2)LinkedLIst底层原理分析

        (1)LinkedList底层成员解释说明

1.LinkedList底层成员
  transient int size = 0;  元素个数
  transient Node<E> first; 第一个节点对象
  transient Node<E> last;  最后一个节点对象
  
2.Node代表的是结点对象
   private static class Node<E> {
        E item;//节点上的元素
        Node<E> next;//记录着下一个节点地址
        Node<E> prev;//记录着上一个节点地址

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

(2)LinkedList底层add方法源码分析

LinkedList<String> list = new LinkedList<>();
list.add("a");
list.add("b");    

void linkLast(E e) {
    // 将当前的last节点赋值给临时变量l
    final Node<E> l = last;
    // 创建一个新节点,其前驱节点为l,元素值为e,后继节点为null
    final Node<E> newNode = new Node<>(l, e, null);
    // 将最后一个节点指针指向新节点
    last = newNode;
    // 如果l为null,说明链表为空,将first指针也指向新节点
    if (l == null)
        first = newNode;
    // 如果l不为null,将l的后继节点指向新节点
    else
        l.next = newNode;
    // 链表大小增加1
    size++;
    // 修改次数增加1
    modCount++;
}
/**   双向链的存储 ,,,二分法查找     比单向链方便的一个体现 **/

 

 (3)LinkedList底层get方法源码分析

public E get(int index) {
    // 检查Index是否合法
    checkElementIndex(index);
    // 返回指定位置节点的元素
    return node(index).item;
} 

// 根据索引获取节点
Node<E> node(int index) {
    // 如果索引超过了元素数量,抛出IndexOutOfBoundsException
    // assert isElementIndex(index);

    if (index < (size >> 1)) {//用二分法查询
        Node<E> x = first;
        // 从头部向后遍历直到找到指定索引的节点
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        // 从尾部向前遍历直到找到指定索引的节点
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    } 
}

六、增强for的使用

1)基本使用

/**  代码演示   **/

public class Demo01For {
    public static void main(String[] args) {
        // 创建一个ArrayList并添加元素
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张翠山");
        list.add("张大彪");
        list.add("李云龙");
        list.add("楚云飞");
        list.add("魏大勇");
        list.add("秀琴大妹子");
        list.add("二营长");

        // 使用增强for循环遍历ArrayList并打印每个元素
        for (String s : list) {
            System.out.println(s);
        }

        System.out.println("==============");

        // 创建一个数组并赋初值
        int[] arr = {1,2,3,4,5};
        // 使用增强for循环遍历数组并打印每个元素
        for (int i : arr) {
            System.out.println(i);
        }
    }
}

2)注意点

 七、Collection集合工具类

public class Demo01Collections {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        // static <T> boolean addAll(Collection<? super T> c, T... elements)->批量添加元素
        Collections.addAll(list,"张三","李四","王五","赵六","田七","猪八");//向集合中添加若干元素
        System.out.println(list);//输出添加列表
        List<String> list1 = Arrays.asList("张三", "李四", "王五");
        System.out.println("list1 = " + list1);

        System.out.println("===========================================");
        // static void shuffle(List<?> list) ->将集合中的元素顺序打乱
        Collections.shuffle(list);
        System.out.println(list);

        System.out.println("===========================================");

        ArrayList<String> list2 = new ArrayList<>();//创建一个 String类型的集合,并逐个添加元素
        list2.add("by");
        list2.add("c");
        list2.add("d");
        list2.add("a");
        list2.add("bi");
        // static <T> void sort(List<T> list) ->将集合中的元素按照默认规则排序 -> ASCII
        Collections.sort(list2);//按照默认规则排序
        System.out.println(list2);//输出
    }
}
static <T> void sort(List<T> list, Comparator<? super T> c)->将集合中的元素按照指定规则排序
    
Comparator:接口,可以用作比较
    方法:int compare(T o1, T o2)->实现比较的方法
            o1-o2:升序
            o2-o1:降序 

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Demo02Collections {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("柳岩",36));
        list.add(new Person("涛哥",16));
        list.add(new Person("曼曼",46));

        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });
        System.out.println(list);
    }
}
public class Person implements Comparable<Person>{
 private String name;
 private Integer age;

 public Person() {
 }

 public Person(String name, Integer age) {
     this.name = name;
     this.age = age;
 }

 public String getName() {
     return name;
 }

 public void setName(String name) {
     this.name = name;
 }

 public Integer getAge() {
     return age;
 }
 public Integer getAge() {
     return age;
 }

 public void setAge(Integer age) {
     this.age = age;
 }

 @Override
 public String toString() {
     return "Person{" +
             "name='" + name + '\'' +
             ", age=" + age +
             '}';
 }

 @Override
 public int compareTo(Person o) {
     return this.getAge()-o.getAge();
 }
}
public class Demo02Collections {
 public static void main(String[] args) {
     ArrayList<Person> list = new ArrayList<>();
     list.add(new Person("柳岩",36));
     list.add(new Person("涛哥",16));
     list.add(new Person("曼曼",46));

     /*Collections.sort(list, new Comparator<Person>() {
         @Override
         public int compare(Person o1, Person o2) {
             return o1.getAge()-o2.getAge();
         }
     });*/

     Collections.sort(list);//元素里面已经实现了排序规则,所以排序的时候直接传集合
     System.out.println(list);
 }
}

八、泛型

1)为什么要使用泛型?

public class Demo1FanXing {
    public static void main(String[] args) {
        //定义一个集合,存储整型,字符串,布尔等类型数据,获取元素中字符串的长度
        ArrayList<Object> list = new ArrayList<>();
        list.add(1);
        list.add("abc");
        list.add("def");
        list.add(2.5);
        list.add(true);

        for (Object o : list) {
            String s = (String) o;//ClassCastException
            System.out.println(s.length());//父类类型调用不了子类方法,所以强制转换,向下转型
        }//然后会报错,会出现编译时异常
    }
}
//object 类型去定义集合中的元素类型,极容易出现ClassCastException异常,类型转换异常   这就是不使用泛型的原因

 2)泛型的定义

(1)含有泛型的类

public class MyArrayList<E>{//E此时就跟个占位符一样,无所谓的 代表
    public void add(E e){//e变量名 E会和类上的E类型一致   返回值类型也可以写成e
    
        System.out.println(e);
    }
}
public class Test01 {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();//传一个字符串
        list.add("abc");//统一引用类型为字符串

        System.out.println("==========================");

        MyArrayList<Integer> list2 = new MyArrayList<>();
        list2.add(1);//统一引用类型为整型
    }
}

 (2)含有泛型的方法

public class Person {//含有泛型的一个方法
    public <E> void eat(E e){
        System.out.println(e);
    }
}
public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        //调用的时候确定泛型中的引用类型是什么  String还是Integer
        //想传什么类型就传什么类型。在调用的时候确定就行了
        person.eat("哈哈哈");
        person.eat(1);
    }
}

 (3)含有泛型的接口

public interface MyList<E>{//定义一个泛型接口 MyList
    public abstract void add(E e);//定义一个抽象方法  参数类型和泛型保持一致  或者E也可以替换成其他引用数据类型
}
public class MyArrayList<E> implements MyList<E>{
    @Override
    public void add(E e) {//实现add类的时候
        System.out.println(e);
    }
}
public class Test01 {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();
        list.add("我是MyArrayList的add方法");//第一种:new实现类对象的时候确定类型
    }
}
public interface MyIterator<E> {//实现一个接口
    E next();
}
public class MyScanner implements MyIterator<String>{
    @Override//直接重写
    public String next() {//实现类的时候直接确定泛型类型为String
        return "重写的next方法";//返回值变成字符串
    }
}
public class Test02 {
    public static void main(String[] args) {
        MyScanner myScanner = new MyScanner();
        String data = myScanner.next();
        System.out.println("data = " + data);//返回一个字符串类型的泛型,给实现类,并输出
    }
}

3)泛型的高级应用

(1)泛型通配符

public class Test01 {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();//new一个ArrayList集合并逐步添加元素
        list1.add("张三");
        list1.add("李四");
        list1.add("王五");
        list1.add("赵六");

        ArrayList<Integer> list2 = new ArrayList<>();//迭代器
        list2.add(1);
        list2.add(2);

        method(list1);
        method(list2);
    }
	//			使用泛型通配符,可以接受任何类型,诸如上述的String和Integer,也可以省略不写
    public static void method(ArrayList<?> list){
        for (Object o : list) {
            System.out.println(o);/输出调用集合中的元素
        }
    }
}

?的引出问题

(2)泛型的上限下限

/**
 *子父类关系
 * Integer -> Number -> Object
 *
 * String -> Object
 */
public class Test02 {
    public static void main(String[] args) {
        //四个集合
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();
        ArrayList<Number> list3 = new ArrayList<>();
        ArrayList<Object> list4 = new ArrayList<>();
        get1(list1);
        //get1(list2); //报错,String和Number没有关系
        get1(list3);
        //get1(list4);//报错,Object类型是Number的父类,传下限

        System.out.println("=================");

        //get2(list1);//报错,Integer是Number的子类,传上限
        //get2(list2);//报错,String和Number没有关系
        get2(list3);
        get2(list4);
    }

    //上限  ?只能接收extends后面的本类类型以及子类类型
    public static void get1(Collection<? extends Number> collection){

    }

    //下限  ?只能接收super后面的本类类型以及父类类型
    public static void get2(Collection<? super Number> collection){

    }
}

 斗地主案例(扩展)

(1)案例介绍

(2)案例分析

 

 (3)代码演示

 package com.atguiguday02.gg_poker;
/**
 *
 实现步骤:
 1.创建集合存储花色  color
 2.创建集合存储牌号  number
 3.创建集合存储组合好的牌  poker
 4.遍历color和number集合进行组合,存储到poker集合中
 5.利用Collections.shuffle打乱poker集合
 6.创建四个集合分别代表
 玩家1:player1
 玩家2:player2
 玩家3:player3
 底牌:dipai
 7.让poker的索引%3,取余数,根据不同的余数,决定存储到哪个玩家集合中
 8.遍历玩个玩家集合以及底牌集合
 *
 *
 *
 * **/
import java.util.ArrayList;
import java.util.Collections;

public class Poker {
    public static void main(String[] args) {
       //1.创建集合存储四种花色  color
        ArrayList<String> color = new ArrayList<>();
        color.add("♠");//黑桃
        color.add("♥");//红桃
        color.add("♣");//梅花
        color.add("♦");//方片
        //System.out.println(color);
        //可以输出集合中的基础花色
        //2.创建集合存储牌号  number
        ArrayList<String> number = new ArrayList<>();
        for (int i = 2; i <= 10; i++) {
            number.add(i+"");
        }//依次存入2~10花色,然后接着逐个添加进集合number
        number.add("J");
        number.add("Q");
        number.add("K");
        number.add("A");//集合添加完毕 2开始尖结束
        //System.out.println(number);

        //3.创建集合存储组合好的牌  poker
        ArrayList<String> poker = new ArrayList<>();
        //4.遍历color和number集合进行组合,存储到poker集合中
        for (String s1 : color) {
            for (String s2 : number) {
                poker.add(s1+s2);
            }
        }
        //System.out.println(poker);
        //输出存储好的拍
        poker.add("☀");//小王
        poker.add("🌙");//大王

       //5.利用Collections.shuffle打乱poker集合
        Collections.shuffle(poker);//将存储好的排,集合直接打乱
       /* 6.创建四个集合分别代表
        玩家1:player1
        玩家2:player2
        玩家3:player3
        底牌:dipai*/
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        //7.让poker的索引%3,取余数,根据不同的余数,决定存储到哪个玩家集合中
        //                 //存储牌额数量
        for (int i = 0; i < poker.size(); i++) {
            String pai = poker.get(i);//取出集合中对应的元素
            if (i>=51){//存底牌  51  52  53
                dipai.add(pai);
            }else if(i%3==0){//玩家1
                player1.add(pai);
            }else if(i%3==1){//玩家2
                player2.add(pai);
            }else if(i%3==2){//玩家3
                player3.add(pai);
            }
        }
        //8.遍历玩个玩家集合以及底牌集合
        //对几个玩家集合进行赋名字操作
        System.out.println("曼曼:"+player1);
        System.out.println("涛哥:"+player2);
        System.out.println("柳岩:"+player3);
        System.out.println("底牌:"+dipai);
    }
}
 package com.atguiguday02.gg_poker;
/**
 *
 实现步骤:
 1.创建集合存储花色  color
 2.创建集合存储牌号  number
 3.创建集合存储组合好的牌  poker
 4.遍历color和number集合进行组合,存储到poker集合中
 5.利用Collections.shuffle打乱poker集合
 6.创建四个集合分别代表
 玩家1:player1
 玩家2:player2
 玩家3:player3
 底牌:dipai
 7.让poker的索引%3,取余数,根据不同的余数,决定存储到哪个玩家集合中
 8.遍历玩个玩家集合以及底牌集合
 *
 *
 *
 * **/
import java.util.ArrayList;
import java.util.Collections;

public class Poker {
    public static void main(String[] args) {
       //1.创建集合存储四种花色  color
        ArrayList<String> color = new ArrayList<>();
        color.add("♠");//黑桃
        color.add("♥");//红桃
        color.add("♣");//梅花
        color.add("♦");//方片
        //System.out.println(color);
        //可以输出集合中的基础花色
        //2.创建集合存储牌号  number
        ArrayList<String> number = new ArrayList<>();
        for (int i = 2; i <= 10; i++) {
            number.add(i+"");
        }//依次存入2~10花色,然后接着逐个添加进集合number
        number.add("J");
        number.add("Q");
        number.add("K");
        number.add("A");//集合添加完毕 2开始尖结束
        //System.out.println(number);

        //3.创建集合存储组合好的牌  poker
        ArrayList<String> poker = new ArrayList<>();
        //4.遍历color和number集合进行组合,存储到poker集合中
        for (String s1 : color) {
            for (String s2 : number) {
                poker.add(s1+s2);
            }
        }
        //System.out.println(poker);
        //输出存储好的拍
        poker.add("☀");//小王
        poker.add("🌙");//大王

       //5.利用Collections.shuffle打乱poker集合
        Collections.shuffle(poker);//将存储好的排,集合直接打乱
       /* 6.创建四个集合分别代表
        玩家1:player1
        玩家2:player2
        玩家3:player3
        底牌:dipai*/
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        //7.让poker的索引%3,取余数,根据不同的余数,决定存储到哪个玩家集合中
        //                 //存储牌额数量
        for (int i = 0; i < poker.size(); i++) {
            String pai = poker.get(i);//取出集合中对应的元素
            if (i>=51){//存底牌  51  52  53
                dipai.add(pai);
            }else if(i%3==0){//玩家1
                player1.add(pai);
            }else if(i%3==1){//玩家2
                player2.add(pai);
            }else if(i%3==2){//玩家3
                player3.add(pai);
            }
        }
        //8.遍历玩个玩家集合以及底牌集合
        //对几个玩家集合进行赋名字操作
        System.out.println("曼曼:"+player1);
        System.out.println("涛哥:"+player2);
        System.out.println("柳岩:"+player3);
        System.out.println("底牌:"+dipai);
    }
}
public class Poker2 {
    public static void main(String[] args) {
       //1.创建数组存储花色  color
        String[] color = "♠-♥-♣-♦".split("-");
        //System.out.println(color);
        //2.创建数组存储牌号  number
        String[] number = "2-3-4-5-6-7-8-9-10-J-Q-K-A".split("-");
        //System.out.println(number);

        //3.创建集合存储组合好的牌  poker
        ArrayList<String> poker = new ArrayList<>();
        //4.遍历color和number集合进行组合,存储到poker集合中
        for (String s1 : color) {
            for (String s2 : number) {
                poker.add(s1+s2);
            }
        }
        //System.out.println(poker);
        poker.add("☀");
        poker.add("🌙");

       //5.利用Collections.shuffle打乱poker集合
        Collections.shuffle(poker);
       /* 6.创建四个集合分别代表
        玩家1:player1
        玩家2:player2
        玩家3:player3
        底牌:dipai*/
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        //7.让poker的索引%3,取余数,根据不同的余数,决定存储到哪个玩家集合中
        for (int i = 0; i < poker.size(); i++) {
            String pai = poker.get(i);
            if (i>=51){
                dipai.add(pai);
            }else if(i%3==0){
                player1.add(pai);
            }else if(i%3==1){
                player2.add(pai);
            }else if(i%3==2){
                player3.add(pai);
            }
        }
        //8.遍历玩个玩家集合以及底牌集合

        System.out.println("曼曼:"+player1);
        System.out.println("涛哥:"+player2);
        System.out.println("柳岩:"+player3);
        System.out.println("底牌:"+dipai);
    }
}

 九、Set集合

(1)Set集合介绍

 (2)HashSet集合的介绍

public class Demo01Set {
    public static void main(String[] args) {
        HashSet<String> set1 = new HashSet<>();
        set1.add("张三");//向集合中逐个添加元素
        set1.add("李四");
        set1.add("王五");
        set1.add("赵六");
        set1.add("田七");
        set1.add("张三");
        System.out.println(set1);//无序,指的是存进去的时候,跟第一次取出来的不一样

        System.out.println("--------------------");
//迭代器遍历
        Iterator<String> iterator = set1.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("-------------------");

        for (String s : set1) {
            System.out.println(s);
        }

    }
}

 

(3)LinkedHashSet的介绍以及使用

public class Demo02Set {
    public static void main(String[] args) {
        LinkedHashSet<String> set1 = new LinkedHashSet<>();
        set1.add("张三");
        set1.add("李四");
        set1.add("王五");
        set1.add("赵六");
        set1.add("田七");
        set1.add("张三");
        System.out.println(set1);

        System.out.println("--------------------");

        Iterator<String> iterator = set1.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("-------------------");

        for (String s : set1) {
            System.out.println(s);
        }

    }
}

(4)哈希值

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

(5)字符串的哈希值是如何算出来的

public int hashCode() {
    int h = hash; // 存储先前计算出的哈希值
    if (h == 0 && value.length > 0) {
        char val[] = value;

        // 遍历字符串中的每个字符
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i]; // 将字符转换为整数,并与已有哈希值进行运算
        }
        hash = h; // 将计算得到的哈希值存储起来,以备之后的调用
    }
    return h; // 返回最终的哈希值
}

 【计算过程】

(6)HashSet的存储去重复的过程

public class Demo01HashSet {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("abc");
        set.add("通话");
        set.add("重地");
        set.add("abc");
        System.out.println(set);
    }
}

(7)HashSet存储自定义类型如何去重复

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class Demo02HashSet {
    public static void main(String[] args) {
        HashSet<Person> set = new HashSet<>();
        set.add(new Person("柳岩",36));
        set.add(new Person("涛哥",18));
        set.add(new Person("曼曼",48));//存储自定义对象
        set.add(new Person("曼曼",48));
        System.out.println(set);
    }
}

 十、Map集合

1)Map的介绍

2)HashMap的介绍与使用

public class Demo01HashMap {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("柳岩","涛哥");
        map.put("曼曼","涛哥");
        map.put("金莲","大郎");
        map.put("黛玉","宝玉");
        map.put("曼曼","大郎");
        map.put(null,null);
        System.out.println(map);

        //V remove(Object key)  ->根据key删除键值对,返回的是被删除的value
        String value = map.remove("黛玉");
        System.out.println(value);
        System.out.println(map);

        // V get(Object key) -> 根据key获取value
        System.out.println(map.get("曼曼"));

        // boolean containsKey(Object key)  -> 判断集合中是否包含指定的key
        System.out.println(map.containsKey("曼曼"));

        //Collection<V> values() -> 获取结合中所有的value,转存到Collection集合中
        Collection<String> collection = map.values();
        System.out.println(collection);

    }
}

public class Demo02LinkedHashMap {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        map.put("柳岩","涛哥");
        map.put("曼曼","涛哥");
        map.put("金莲","大郎");
        map.put("黛玉","宝玉");
        map.put("曼曼","大郎");
        map.put(null,null);
        System.out.println(map);
    }
}

3)HashMap中的两种遍历方式

(1)方式1:获取key,根据key再获取value

public class Demo03HashMap {
    public static void main(String[] args) {
        // 创建 HashMap 对象
        HashMap<String, String> hashMap = new HashMap<>();

        // 向 HashMap 中添加键值对
        hashMap.put("柳岩","涛哥");
        hashMap.put("金莲","大郎");
        hashMap.put("丁一","乔碧萝");
        hashMap.put("锟锟","丁真");

        // 获取 HashMap 中所有的 key,并存入 Set 集合
        Set<String> set = hashMap.keySet();
        System.out.println("输出HashMap集合中的key,并存入集合Set集合");
        System.out.println(set);

        // 遍历 Set 集合,获取每个 key,并输出对应的 value
        for (String key : set) {
            String value = hashMap.get(key);
            //HashMap 中根据给定的 key 获取对应的 value 值。
            System.out.println(key + "..." + value);
        }
//在这段代码中,通过遍历 Set 集合获取每个 key,然后使用 hashMap.get(key) 来获取对应的 value 值。
// 通过这个操作,我们可以逐个输出 HashMap 中的所有键值对
    }
}

(2)方式2:同时获取key和value‘

package com.atguiguday02.kk_map;

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

public class Demo04HashMap {
    public static void main(String[] args) {
        // 创建 HashMap 对象
        HashMap<String, String> hashMap = new HashMap<>();

        // 向 HashMap 中添加键值对
        hashMap.put("柳岩","涛哥");
        hashMap.put("金莲","大郎");
        hashMap.put("丁一","乔碧萝");
        hashMap.put("锟锟","丁真");

        // 获取 HashMap 中所有的键值对,并存入 Set 集合
        Set<Map.Entry<String, String>> set = hashMap.entrySet();
        /**
         *
         * 使用 entrySet() 方法可以获取到 HashMap 中所有的键值对,
         * 然后遍历 Set 集合,获取每个键值对的键和值,并输出到控制台。
         * **/
        // 遍历 Set 集合,获取每个键值对并输出
        for (Map.Entry<String, String> entry : set) {
            String key = entry.getKey(); // 获取键
            String value = entry.getValue(); // 获取值
            System.out.println(key + "..." + value);
        }
    }
}

4)HashMap存储自定义对象如何保证key唯一

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
   @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class Demo05HashMap {
    public static void main(String[] args) {
        HashMap<Person, String> map = new HashMap<>();
        map.put(new Person("柳岩",36),"湖南");
        map.put(new Person("曼曼",45),"辽宁");
        map.put(new Person("涛哥",18),"河北");
        map.put(new Person("涛哥",18),"北京");
        System.out.println(map);
    }
}

 5)Map的综合练习

 【代码演示】

public class Demo01Map {
    public static void main(String[] args) {
        //1.创建Scanner对象,键盘录入一个字符串:data
        Scanner sc = new Scanner(System.in);
        System.out.println("请您输入一个字符串:");
        String data = sc.next();
        //2.创建HashMap
        HashMap<String, Integer> hashMap = new HashMap<>();
        //3.遍历data,将每一个元素获取出来
        char[] chars = data.toCharArray();
        for (char aChar : chars) {
            String key = aChar+"";
            //4.挨个判断,集合中是否包含指定的key
            if (!hashMap.containsKey(key)){
            //5.如果不包含,证明字符第一次出现,我们就将此字符和1存到集合中
                hashMap.put(key,1);
            }else{
            //6.如果包含,根据字符获取对应的value,让value++,重新存到集合中
                Integer value = hashMap.get(key);
                value++;
                hashMap.put(key,value);
            }
        }
        System.out.println(hashMap);
    }
}

6)斗地主(Map版本)

 【代码实现】

public class Demo02Poker {
    public static void main(String[] args) {
        //1.创建数组,存储花色
        String[] color = "♠-♥-♣-♦".split("-");
        //2.创建数组,存储牌号
        String[] number = "2-3-4-5-6-7-8-9-10-J-Q-K-A".split("-");
        //3.创建HashMap存储牌面
        HashMap<Integer, String> pokerMap = new HashMap<>();
        //4.创建一个ArrayList集合,专门存储牌面对应的key
        ArrayList<Integer> list = new ArrayList<>();
        //5.组合牌,存储到Map集合中
        int key = 2;
        for (String s1 : number) {
            for (String s2 : color) {
                String poker = s2+s1;
                pokerMap.put(key,poker);
                list.add(key);
                key++;
            }
        }
        pokerMap.put(0,"大🃏");
        pokerMap.put(1,"小🃏");
        list.add(0);
        list.add(1);
        //System.out.println(pokerMap);

        //6.洗牌
        Collections.shuffle(list);
        //7.发牌
        ArrayList<Integer> player1 = new ArrayList<>();
        ArrayList<Integer> player2 = new ArrayList<>();
        ArrayList<Integer> player3 = new ArrayList<>();
         ArrayList<Integer> dipai = new ArrayList<>();
        //7.让poker的索引%3,取余数,根据不同的余数,决定存储到哪个玩家集合中
        for (int i = 0; i < list.size(); i++) {
            Integer pai = list.get(i);
            if (i>=51){
                dipai.add(pai);
            }else if(i%3==0){
                player1.add(pai);
            }else if(i%3==1){
                player2.add(pai);
            }else if(i%3==2){
                player3.add(pai);
            }
        }
        //8.排序
        Collections.sort(player1);
        Collections.sort(player2);
        Collections.sort(player3);
        Collections.sort(dipai);

        //9.看牌
        lookPoker("柳岩",player1,pokerMap);
        lookPoker("曼曼",player2,pokerMap);
        lookPoker("涛哥",player3,pokerMap);
        lookPoker("底牌",dipai,pokerMap);
    }

    public static void lookPoker(String name,ArrayList<Integer> list,HashMap<Integer, String> map){
        System.out.print(name+": ");
        for (Integer key : list) {
            System.out.print(map.get(key)+" ");
              }
        System.out.println();
    }
}

十一、TreeSet

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

import java.util.Comparator;
import java.util.TreeSet;

public class Demo01TreeSet {
    public static void main(String[] args) {
        // 创建 TreeSet 对象
        TreeSet<String> treeSet = new TreeSet<>();

        // 向 TreeSet 中添加元素
        treeSet.add("b");
        treeSet.add("d");
        treeSet.add("a");
        treeSet.add("c");

        // 输出 TreeSet,按照自然顺序进行排序
        System.out.println(treeSet);
        System.out.println("================");

        // 创建 TreeSet 对象,并传入自定义的 Comparator 排序器
        TreeSet<Person> treeSet1 = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge(); // 按照年龄进行排序
            }
        });

        // 向 TreeSet 中添加 Person 对象
        treeSet1.add(new Person("柳岩", 36));
        treeSet1.add(new Person("涛哥", 18));
        treeSet1.add(new Person("曼曼", 48));

        // 输出 TreeSet,按照自定义的 Comparator 排序器进行排序
        System.out.println(treeSet1);
    }
}

十二、TreeMap

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
package com.atguiguday03.b_tree;

import java.util.Comparator;
import java.util.TreeMap;

public class Demo02TreeMap {
    public static void main(String[] args) {
        // 创建 TreeMap 对象,存储字符串类型的键值对
        TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("d","低头思故乡");
        treeMap.put("a","床前明月光");
        treeMap.put("c","举头望明月");
        treeMap.put("b","疑是地上霜");
        System.out.println(treeMap);

        System.out.println("================================");

        // 创建 TreeMap 对象,并传入自定义的 Comparator 排序器,存储 Person 对象作为键
        TreeMap<Person, String> treeMap1 = new TreeMap<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge()-o1.getAge(); // 根据年龄降序排序
            }
        });

        // 向 TreeMap 中添加键值对
        treeMap1.put(new Person("柳岩",36),"湖南");
        treeMap1.put(new Person("曼曼",48),"辽宁");
        treeMap1.put(new Person("涛哥",18),"廊坊");
        System.out.println(treeMap1);
    }
}

十三、Hashtable和Vector集合(了解)

1)Hashtable集合

import java.util.Hashtable;
import java.util.Set;

public class Demo01Hashtable {
    public static void main(String[] args) {
        // 创建一个 Hashtable 对象
        Hashtable<String, String> hashtable = new Hashtable<>();
        
        // 向 Hashtable 中添加键值对
        hashtable.put("张无忌","赵敏");
        hashtable.put("张翠山","殷素素");
        hashtable.put("张三丰","郭襄");
        hashtable.put("范瑶","灭绝师太");
        hashtable.put("杨逍","纪晓芙");
        
        // 不可以存储 null 键或 null 值
        // hashtable.put(null,null);
        
        // 打印 Hashtable 的键值对
        System.out.println(hashtable);

        // 获取 Hashtable 中所有键的集合
        Set<String> set = hashtable.keySet();
        
        // 遍历键的集合,获取每个键对应的值并输出
        for (String key : set) {
            System.out.println(hashtable.get(key));
        }
    }
}

 Hashtable和HashMap区别:

2)vector集合

package com.atguiguday03.d_vector.e_properties;

import java.util.Properties;
import java.util.Set;

public class Demo01Properties {
    public static void main(String[] args) {
        // 创建一个 Properties 对象
        Properties properties = new Properties();

        // 设置属性值
        properties.setProperty("username","root");
        properties.setProperty("password","root");

        // 打印 Properties 对象
        System.out.println(properties);

        // 获取所有属性的键的集合
        Set<String> set = properties.stringPropertyNames();

        // 遍历键的集合,获取每个键对应的值并输出
        for (String key : set) {
            String value = properties.getProperty(key);
            System.out.println(key + "..." + value);
        }
    }
}

 【vector底层源码分析】

Vector()->构造一个空向量,使其内部数据数组的大小为 10,其标准容量增量为零
========================================
Vector<String> vector = new Vector<>()
========================================
capacityIncrement:标准容量增强,默认为0    
elementData:Vector底层数组
 
public Vector() {
 this(10);
}    
public Vector(int initialCapacity->10) {
 this(initialCapacity->10, 0 -> 标准容量增量);
}
public Vector(int initialCapacity->10, int capacityIncrement->0) {
 super();//不用管
 if (initialCapacity < 0)
     throw new IllegalArgumentException("Illegal Capacity: "+
                                        initialCapacity);
 //this.elementData = new Object[10]
 this.elementData = new Object[initialCapacity];
 this.capacityIncrement = capacityIncrement;//0
}

========================================
vector.add("a");
========================================
public synchronized boolean add(E e) {
 modCount++;
 ensureCapacityHelper(elementCount + 1 ->11);//假如数组存了10个元素,正在存第11个
 elementData[elementCount++] = e;
 return true;
} 
private void ensureCapacityHelper(int minCapacity->11) {
 // overflow-conscious code
 if (minCapacity - elementData.length > 0)
     grow(minCapacity->11);//扩容相关方法
}

private void grow(int minCapacity->11) {
     // overflow-conscious code
     int oldCapacity = elementData.length;//10
     int newCapacity = oldCapacity + ((capacityIncrement > 0) 
                                      capacityIncrement : oldCapacity);->20
      //算新容量
     if (newCapacity - minCapacity < 0)
         newCapacity = minCapacity;
     if (newCapacity - MAX_ARRAY_SIZE > 0)
         newCapacity = hugeCapacity(minCapacity);
    //elementData = Arrays.copyOf(老数组,20)
     elementData = Arrays.copyOf(elementData, newCapacity);
}
Vector(int initialCapacity, int capacityIncrement) 
==================================================
Vector<String> vector = new Vector<>(10,5);   
==================================================
public Vector(int initialCapacity->10, int capacityIncrement->5) {
 super();
 if (initialCapacity < 0)
     throw new IllegalArgumentException("Illegal Capacity: "+
                                        initialCapacity);
 //this.elementData = new Object[10]
 this.elementData = new Object[initialCapacity];
 this.capacityIncrement = capacityIncrement;//5
}
=================================================== 
vector.add("a");
===================================================
public synchronized boolean add(E e) {
 modCount++;
 ensureCapacityHelper(elementCount + 1->11);//假如还是超出了原始数组容量,还是存第11个
 elementData[elementCount++] = e;
 return true;
}  

private void ensureCapacityHelper(int minCapacity->11) {
 // overflow-conscious code
 if (minCapacity - elementData.length > 0)
     grow(minCapacity);
}
private void grow(int minCapacity->11) {
 // overflow-conscious code
 int oldCapacity = elementData.length;//10
 //int newCpacity = 10+5 = 15
 int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                  capacityIncrement : oldCapacity);
 if (newCapacity - minCapacity < 0)
     newCapacity = minCapacity;
 if (newCapacity - MAX_ARRAY_SIZE > 0)
     newCapacity = hugeCapacity(minCapacity);
 //elementData = Arrays.copyOf(数组,15)
 elementData = Arrays.copyOf(elementData, newCapacity);
}                                                        
                                  

十四、Properties集合(属性集)

import java.util.Properties;
import java.util.Set;

public class Demo01Properties {
    public static void main(String[] args) {
        // 创建一个 Properties 对象
        Properties properties = new Properties();
        
        // 设置属性值
        properties.setProperty("username","root");
        properties.setProperty("password","1234");
        
        // 打印 Properties 对象
        System.out.println(properties);

        // 获取所有属性的键的集合
        Set<String> set = properties.stringPropertyNames();
        
        // 遍历键的集合,获取每个键对应的值并输出
        for (String key : set) {
            String value = properties.getProperty(key);
            System.out.println(key + "..." + value);
        }
    }
}

十五、集合嵌套

1)List嵌套List

import java.util.ArrayList;

public class Demo01ListInList {
    public static void main(String[] args) {
        // 创建一个ArrayList对象list1,并添加元素
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("洪七公");
        list1.add("黄老邪");
        list1.add("欧阳锋");
        list1.add("一灯大师");
        list1.add("王重阳");

        // 创建一个ArrayList对象list2,并添加元素
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("东方不败");
        list2.add("岳不群");
        list2.add("林平之");

        // 创建一个ArrayList对象list,将list1和list2添加进去,所以泛型要写ArrayList
        ArrayList<ArrayList<String>> list = new ArrayList<>();
        list.add(list1);
        list.add(list2);

        // 遍历list集合,将两个小集合遍历出来
        for (ArrayList<String> arrayList : list) {
            for (String s : arrayList) {
                System.out.println(s);
            }
        }
    }
}

2)list嵌套Map

package com.atguiguday03.e_list;

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

public class Demo02ListInMap {
    public static void main(String[] args) {
        // 创建HashMap对象map1,并添加键值对
        HashMap<Integer, String> map1 = new HashMap<>();
        map1.put(1,"张三");
        map1.put(2,"李四");

        // 创建HashMap对象map2,并添加键值对
        HashMap<Integer, String> map2 = new HashMap<>();
        map2.put(1,"黄晓明");
        map2.put(2,"刘德华");

        // 创建ArrayList对象list,将map1和map2添加进去
        ArrayList<HashMap<Integer, String>> list = new ArrayList<>();
        list.add(map1);
        list.add(map2);

        // 遍历list集合,将每个map中的键值对遍历出来
        for (HashMap<Integer, String> map : list) {
            Set<Map.Entry<Integer, String>> entries = map.entrySet();
            for (Map.Entry<Integer, String> entry : entries) {
                System.out.println(entry.getKey()+"..."+entry.getValue());
            }
        }
    }
}

 会遍历就行

3)Map嵌套Map

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

public class Demo03MapInMap {
    public static void main(String[] args) {
        // 创建HashMap对象map1,并添加键值对
        HashMap<Integer, String> map1 = new HashMap<>();
        map1.put(1, "张三");
        map1.put(2, "李四");

        // 创建HashMap对象map2,并添加键值对
        HashMap<Integer, String> map2 = new HashMap<>();
        map2.put(1, "黄晓明");
        map2.put(2, "刘德华");

        // 创建HashMap对象map,并将map1和map2添加进去
        HashMap<String, HashMap<Integer, String>> map = new HashMap<>();
        map.put("javase", map1);
        map.put("javaee", map2);

        // 获取map的键集合
        Set<String> set = map.keySet();
        // 遍历键集合,依次取出对应的HashMap,并遍历其中的键值对
        for (String key : set) {
            // 获取对应的HashMap
            HashMap<Integer, String> hashMap = map.get(key);
            // 获取HashMap的键值对集合
            Set<Map.Entry<Integer, String>> entries = hashMap.entrySet();
            // 遍历键值对集合,输出键和值
            for (Map.Entry<Integer, String> entry : entries) {
                System.out.println(entry.getKey() + "..." + entry.getValue());
            }
        }
    }
}

十六、哈希表的存储过程

1)HashMap无参数构造方法的分析

//HashMap中的静态成员变量
static final float DEFAULT_LOAD_FACTOR = 0.75f;
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

解析:使用无参数构造方法创建HashMap对象,将加载因子设置为默认的加载因子,loadFactor=0.75F。

2)HashMap有参数构造方法分析

HashMap(int initialCapacity, float loadFactor) ->创建Map集合的时候指定底层数组长度以及加载因子
    
public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
    	throw new IllegalArgumentException("Illegal initial capacity: " +
    initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
    	initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
    	throw new IllegalArgumentException("Illegal load factor: " +
    loadFactor);
    this.loadFactor = loadFactor;
    this.threshold = tableSizeFor(initialCapacity);//10
}

3)tableSizeFor方法分析

4)Node 内部类分析

static class Node<K,V> implements Map.Entry<K,V> {
     final int hash;
     final K key;
     V value;
     Node<K,V> next;
 Node(int hash, K key, V value, Node<K,V> next) {
     this.hash = hash;
     this.key = key;
     this.value = value;
     this.next = next;
}

5)存储元素的put方法源码

public V put(K key, V value) {
	return putVal(hash(key), key, value, false, true);
}

6)putVal方法源码

Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;

7)resize方法的扩容计算

if (oldCap > 0) {
     if (oldCap >= MAXIMUM_CAPACITY) {
         threshold = Integer.MAX_VALUE;
         return oldTab;
     }
     else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
              oldCap >= DEFAULT_INITIAL_CAPACITY)
         newThr = oldThr << 1; // double threshold
}

解析:计算结果,新的数组容量=原始数组容量<<1,也就是乘以2。

8)确定元素存储的索引

if ((p = tab[i = (n - 1) & hash]) == null)
	 tab[i] = newNode(hash, key, value, null);

9)遇到重复哈希值的对象

Node<K,V> e; K k;
 if (p.hash == hash &&
 	((k = p.key) == key || (key != null && key.equals(k))))
		 e = p;

解析:如果对象的哈希值相同,对象的equals方法返回true,判断为一个对象,进行覆盖操作。

else {
     for (int binCount = 0; ; ++binCount) {
     	if ((e = p.next) == null) {
     		p.next = newNode(hash, key, value, null);
     	if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
     		treeifyBin(tab, hash);
     	break;
 }

总结:

关于集合的,我就写个这么多,写的不好的。

请指出。

举报

相关推荐

0 条评论