List+Set+Map

一、List

1、数据结构与算法

数据结构:数据的存储方式。
常见的数据结构:栈 队列 数组 链表 二叉树 哈希表
栈的数据结构特点:先进后出,后进先出。弹夹就是典型的栈结构
队列的特点:先进的先出,后进的后出

在这里插入图片描述

数组的特点:数组的元素都标有索引,查询快,增删慢。
链表的特点:查询慢,增删快

在这里插入图片描述

list接口下的三个子类特点:
Arraylist集合:底层使用的是数组,查询快,增删慢。线程不安全,效率高。
Linkedlist集合:底层使用的是链表,查询慢,增删快。线程不安全,效率高。
Vector:底层使用的是数组,查询快,增删慢。线程安全,效率低。

2、List

 List概述及特点:
        	元素有序(存的顺序和取的顺序一致),但是不连续,允许存储null值,每一个元素都存在一个索引.元素可以重复.
        void add ( int index, E element)
        在列表的指定位置插入指定元素(可选操作)。
         E get(int index)返回列表中指定位置的元素。

        int indexOf(Object o)
          返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
           int lastIndexOf(Object o)
          返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
          ListIterator<E> listIterator()
          返回此列表元素的列表迭代器(按适当顺序)。
           E remove(int index)
          移除列表中指定位置的元素(可选操作)。
           E set(int index, E element)
          用指定元素替换列表中指定位置的元素(可选操作)。
           List<E> subList(int fromIndex, int toIndex)
          返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。


list的反向遍历:
ListIterator 继承自Iterator  可以使用Iterator中的方法
​	A:ListIterator的特有功能
​		boolean hasPrevious():			是否存在前一个元素
​		E previous():					返回列表中的前一个元素
​		以上两个方法可以实现反向遍历 但是注意 要完成反向遍历之前 要先进行正向遍历  这样指针才能移到最后
​		如果直接反向遍历是没有效果的  因为指针默认位置就在最前面 他前面没有元素

(1)添加与获取

package org.westos.demo2;

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

public class MyTest {
    public static void main(String[] args) {
        List list=new ArrayList();
        list.add(100);
        list.add(800);
        list.add(300);
        list.add("asaa");
        list.add(3.15);
        //  void add ( int index, E element)
        //        在列表的指定位置插入指定元素(可选操作)。
        System.out.println(list);
        System.out.println("----------");
        list.add(0,"李白");
        System.out.println(list);
        list.add(1,"王维");
        System.out.println(list);
        System.out.println("========");
       /* E get(int index)
        返回列表中指定位置的元素。*/

        Object o = list.get(0);
        Object o1 = list.get(1);
        System.out.println(o);
        System.out.println(o1);

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

        int i = list.indexOf(300);
        int i1 = list.lastIndexOf(300);
        System.out.println(i);
        System.out.println(i1);

        System.out.println(list.indexOf(100000));//-1

    }
}

(2)遍历

package org.westos.demo2;

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

public class MyTest3 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new Studnet("李白",22));
        list.add(new Studnet("杜甫",24));
        list.add(new Studnet("王维",26));

        //正向遍历
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
            Object next = listIterator.next();
            System.out.println(next);
        }

        //反向遍历:
        /* 反向遍历:list的反向遍历:
        ListIterator 继承自Iterator  可以使用Iterator中的方法
        	A:ListIterator的特有功能
        		boolean hasPrevious():			是否存在前一个元素
        		E previous():					返回列表中的前一个元素
        		以上两个方法可以实现反向遍历 但是注意 要完成反向遍历之前 要先进行正向遍历  这样指针才能移到最后
        		如果直接反向遍历是没有效果的  因为指针默认位置就在最前面 他前面没有元素*/
        System.out.println("=================");
        while (listIterator.hasPrevious()) {
            Object previous = listIterator.previous();
            System.out.println(previous);
        }
    }
}

3、ArrayList

List接口的大小可变数组的实现,实现了所有可选列表操作,并允许包括null在内的所有元素。
        ArrayList:底层使用的是数组,查询快,增删慢。注意:此实现不是同步的,是线程不安全的。效率高。
        元素有序的(存取顺序一致) 元素编有索引,允许元素重复

(1)遍历方式;

ArrayList:底层使用的是数组,查询快,增删慢。此实现不是同步的,是线程不安全的,效率高。
	遍历方式有四种:
(1)Iterator iterator = list.iterator();//用hasNext和next方法
(2)ListIterator listIterator = list.listIterator();//自己特有的迭代器
(3)for循环,size()和get()方法
ArrayList集合新的迭代方法:
(4)JDK1.8之后提供了一种迭代方法。
void forEach(Consumer<? super E> action)
执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常。
package org.westos.demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.function.Consumer;

public class MyTest {
    public static void main(String[ ] args) {
    //List接口的大小可变数组的实现,实现了所有可选列表操作,并允许包括null在内的所有元素。
        //ArrayList:底层使用的是数组,查询快,增删慢。注意:此实现不是同步的,是线程不安全的。效率高。
        //元素有序的(存取顺序一致) 元素编有索引,允许元素重复

        ArrayList list = new ArrayList();
        list.add(10);
        list.add(20);
        list.add(30);
        list.add(40);
        list.add("aa");
        list.add(null);

        System.out.println(list);
        //遍历方式一:iterato,用hasNext()和next人()方法
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }
        System.out.println("---------");

        //遍历方式二:用for循环
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("========");

        //遍历方式三:用listIterator()方法
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
            Object next = listIterator.next();
            System.out.println(next);
        }

        /*遍历方式四:JDK1.8之后提供了一种迭代方法。
        void forEach(Consumer<? super E> action)
        执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常。*/
        System.out.println("---------");
        list.forEach(new Consumer() {
            @Override
            public void accept(Object o) {
                //o就是集合中的元素
                System.out.println(o);
            }
        });
    }
}

(2)排序方法

ArrayList集合新的排序方法
​	void sort (Comparator < ? super E > c)
​	分类列表使用提供的 Comparator比较元素。
​	排序 Comparator 比较器
package org.westos.demo;

import java.util.ArrayList;
import java.util.Comparator;

public class MyTest2 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(900);
        list.add(400);
        list.add(200);
        list.add(100);
        //list.add("aaa");
        //list.add(3.14);
        System.out.println(list);
        System.out.println("---------");
        //排序方法
        /*void sort (Comparator < ? super E > c)
​	        分类列表使用提供的 Comparator比较元素。
​	        排序 Comparator 比较器
        * */
        list.sort(new Comparator() {
            @Override
            public int compare(Object a, Object b) {
                Integer num= (Integer) a;
                Integer num2= (Integer) b;
                int i = num.intValue();
                int j = num2.intValue();
                //升序排列
                return i-j;

            }
        });
        System.out.println(list);
    }
}

(3)删除和判断

ArrayList集合删除某些元素:
​	boolean removeIf (Predicate < ? super E > filter)
​	删除满足给定谓词的这个集合的所有元素。

判断集合为空的方法:isEmpty();
package org.westos.demo4;

import java.util.ArrayList;
import java.util.function.Predicate;

public class MyTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(100);
        list.add(200);
        list.add(300);
        list.add(400);
        list.add(500);
        //根据索引删除    返回的是你删除的那个元素
        Object remove = list.remove(0);
        System.out.println(remove);
        //根据元素删除    返回的是 是否删除成功
        boolean remove1 = list.remove(new Integer(200));
        System.out.println(remove1);
        System.out.println("=======");

        ArrayList list1 = new ArrayList();
        list1.add(100);
        list1.add(200);
        list1.add(300);
        list1.add(400);
        list1.add(500);
        list1.removeIf(new Predicate() {
            @Override
            public boolean test(Object o) {
                Integer num= (Integer) o;
                return num>300;
            }
        });
        System.out.println(list1);//[100, 200, 300]

 //判断集合是否为空
        boolean empty = list1.isEmpty();
        System.out.println(empty);
        //也可以通过判断集合长度来确定集合是否为空
          if(list.size()==0){
            System.out.println("list集合为空!");
        }
    }
}

4、Vector

Vector集合与ArrayList集合相同,底层数据结构是数组,查询快,增删慢,但是是线程安全的,即同步的但效率低下。

Vector中的方法:
vector集合的一些方法:
(1)添加元素---->vector.add(“ab”);
​	----->vector.addelement(“cd”);
(2)遍历元素:A:
					vector.forEach(new Consumer() {
														@Override
											public void accept(Object obj) {
											System.out.println(obj);
											}
							});

 			B:
 			Vector容器有一个自己的迭代器,可以遍历集合中的元素。
​	Enumeration elements(),返回此向量的组件的枚举。
​	Enumeration 迭代器 hasMoreElements()----->判断还有没有下一个元素
​	nextElement()----->获取下一个元素

 			Enumeration<E> elements() 
          					返回此向量的组件的枚举。 
(3)取第一个元素:vector.firstElement();
​	取最后一个元素:vector.lastElement();
​	根据索引截取一个元素:vector.elementAt(2);

package org.westos.demo4;

import java.util.Enumeration;
import java.util.Vector;
import java.util.function.Consumer;

public class MyTest2 {
    public static void main(String[] args) {
        Vector vector = new Vector();
        //add(E e) 将指定元素添加到此向量的末尾。
        vector.add("aaa");
        vector.add(111);
        vector.add(3.13);
        System.out.println(vector);
        System.out.println("--------");

        /*void addElement(E obj)
        将指定的组件添加到此向量的末尾,将其大小增加 1。*/
        vector.addElement("cd");
        vector.addElement(777);
        System.out.println(vector);
        System.out.println("--------");

        //遍历:方式一,foreach()方法
        vector.forEach(new Consumer() {
            @Override
            public void accept(Object o) {
                System.out.println(o);
            }
        });
        System.out.println("-------------");
        //  遍历方式二:采用elements() 方法
        Enumeration elements = vector.elements();
        while (elements.hasMoreElements()) {
            System.out.println(elements.nextElement());
        }
        System.out.println("--------");
/*
        取第一个元素:vector.firstElement();
​	取最后一个元素:vector.lastElement();
​	根据索引截取一个元素:vector.elementAt(2);*/
        Vector vector1 = new Vector();
        vector1.addElement(1);
        vector1.addElement("aaa");
        vector1.addElement(444);
        vector1.addElement(444.33);

        Object o = vector1.firstElement();
        System.out.println(o);
        Object o1 = vector1.lastElement();
        System.out.println(o1);

        Object o2 = vector1.elementAt(3);
        System.out.println(o2);


    }
}

5、LinkedList

底层数据结构是链表,增删快,查找慢,线程不安全,效率高,此实现不是同步的

LinkedList集合中的方法:
(1)addFirst():在首位置上增加元素
(2)addLast():在末位置上增加元素
(3)getFirst():返回此列表的第一个元素
(4)getLast():返回此列表的最后一个元素
(5)removeFirst():移除并返回此列表的第一个元素
(6)removeLast():移除并返回此列表的最后一个元素
(7)poll():获取并移除此列表的头(第一个元素)
(8)pollFirst():获取并移除此列表的第一个元素,如果此列表为空,则返回null
(9)pollLast():获取并移除此列表的最后一个元素,如果此列表为空,则返回null
(10)pop():从此列表所表示的堆栈处弹出第一个元素
(11)push():将元素推入此列表所表示的堆栈
package org.westos.demo5;

import java.util.LinkedList;

public class MyTest {
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        /*(1)addFirst():在链表的首位置上增加元素
        (2)addLast():在末位置上增加元素
        (3)getFirst():返回此列表的第一个元素
        (4)getLast():返回此列表的最后一个元素
        (5)removeFirst():移除并返回此列表的第一个元素
        (6)removeLast():移除并返回此列表的最后一个元素*/
        list.add(11);
        list.add(22);
        list.add("aaa");
        list.add(44.44);
        System.out.println(list);
        System.out.println("--------");
        list.addFirst(true);
        list.addFirst(false);
        list.addLast(true);
        list.addLast(false);
        System.out.println(list);
        System.out.println("--------");
        Object first = list.getFirst();
        System.out.println(first);
        Object last = list.getLast();
        System.out.println(last);
        System.out.println("=======");
        System.out.println(list);
        System.out.println("--------");
        Object o = list.removeFirst();
        System.out.println("======");
        System.out.println(o);
        Object o1 = list.removeLast();
        System.out.println(o1);
        System.out.println(list);
    }
}

package org.westos.demo5;

import java.util.LinkedList;

public class MyTest2 {
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        list.add(500);
        list.add(400);
        list.add(300);
        list.add(200);
        list.add(100);
        /*(7)poll():获取并移除此列表的头(第一个元素)
        (8)pollFirst():获取并移除此列表的第一个元素,如果此列表为空,则返回null
        (9)pollLast():获取并移除此列表的最后一个元素,如果此列表为空,则返回null
        (10)pop():从此列表所表示的堆栈处弹出第一个元素
        (11)push():将元素推入此列表所表示的堆栈*/
        System.out.println(list);
        Object poll = list.poll();
        System.out.println(poll);
        System.out.println("===========");
        System.out.println(list);

        Object o = list.pollFirst();
        System.out.println(o);
        Object o1 = list.pollLast();
        System.out.println(o1);
        System.out.println("===========");
        System.out.println(list);

        System.out.println("==========");
        Object pop = list.pop();
        System.out.println(pop);
        System.out.println(list);
        list.push(333);
        System.out.println(list);//[333, 200]
    }
}

6、练习题

(1)LinkedList集合框架练习题

    需求:请用LinkedList模拟栈数据结构的集合,并测试
        先进的后出,后进的先出
package org.westos.demo6;

import java.util.LinkedList;

public class MyTest {
    public static void main(String[] args) {
        /*需求:请用LinkedList模拟栈数据结构的集合,并测试
        先进的后出,后进的先出*/
        MyList myList = new MyList();
        myList.add(2);
        myList.add(33);
        myList.add(444);


        Object o = myList.get();
        System.out.println(o);
        o = myList.get();
        System.out.println(o);

        System.out.println(myList.toString());
    }
}
class MyList{
    @Override
    public String toString() {
        return "MyList{" +
                "linkedList=" + linkedList +
                '}';
    }

    private final LinkedList linkedList;

    public MyList(){
        //创建linkedList
         linkedList = new LinkedList();
    }

    //添加元素
    public void add(Object o){
        linkedList.addFirst(o);
    }
    //获取元素
    // 每次都只能获取栈顶元素
    public Object get(){

        Object pop = linkedList.pop();

        linkedList.addLast(pop);
        return pop;
    }
}

(2)ArrayList集合框架练习题

去除集合中的重复元素:要求两种方法:
(1)不能创建新的容器,就在本容器中做
​	(2)创建一个新的容器
package org.westos.demo7;

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

public class MyTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Studnet("李白",22));
        list.add(new Studnet("杜甫",3322));
        list.add(new Studnet("王维",9999));
        list.add(new Studnet("屈原",22));
        list.add(new Studnet("屈原",22));
        list.add(new Studnet("苏轼",666));
        list.add(new Studnet("欧阳修",777));
        System.out.println(list);
        System.out.println("===========================");

        //去除重复元素方式一:创建新集合
        ArrayList list2 = new ArrayList();
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
            Object next = listIterator.next();
            Studnet s= (Studnet) next;
            //这里的contains内部采用的是equals方法,因此我们必须重写equals方法
           if (!list2.contains(s)){

            list2.add(s);
           }

        }
        System.out.println(list2);

        //去除重复元素方式二:要求,不能重建新的容器来做,就在本容器中操作
        //采用选择排序法的思想:用第一个元素和后面的元素进行对比。
        System.out.println("======================");

        for (int i = 0; i < list.size()-1; i++) {
            for(int j=i+1;j<list.size();j++){
                if(list.get(i).equals(list.get(j))){
                    list.remove(j);
                    //原来的1位置上的元素去除以后,下一个位置上就变成了1位置。
                    //但是咱们这时候有一个j++,j就从1变成了2.把此时的1位置就跳过了。直接到了2位置。
                    //就是这个j必须得和i是连着的。不能是中间跨了一个数。跨了一个数就把一个元素丢了
                    j--;//j必须--
                }

            }
        }
        System.out.println(list);
    }
}

7.asList()方法

 Arrays工具类的asList(T...t)方法的使用:
        将数组转换成集合*/
      泛型方法:方法上的泛型,是你在调用方法时,就可以明确方法上泛型的具体数据类型
        static <T> List <T> asList(T...a)
        返回一个受指定数组支持的固定大小的列表。
        
package org.westos.demo8;

import java.util.Arrays;
import java.util.List;

public class MyTest2 {
    public static void main(String[] args) {
        /*  Arrays工具类的asList(T...t)方法的使用:
        将数组转换成集合*/
        //泛型方法:方法上的泛型,是你在调用方法时,就可以明确方法上泛型的具体数据类型
       /* static <T> List <T>
                asList(T...a)
        返回一个受指定数组支持的固定大小的列表。*/

        List<String> strings = Arrays.asList("aaa", "ccc", "ddd");

        List<Integer> integers = Arrays.asList(99, 2, 111);

        //当我传进来的是一个对象数组。他是怎么转换成集合的?他把数组中的元素取出来,再放到集合中
        Integer[] arr= {10, 20, 30};
        List<Integer> integers1 = Arrays.asList(arr);
        System.out.println(integers1.get(0));
        System.out.println(integers1);

        Integer[] arr2={1,2,3};
        Integer[] arr3={5,4,6};
        Integer[] arr4={9,8,300};
        //传进来多个元素是基本数据类型的数组,转换成的集合是,这个集合中,放了多个数组对象
        List<Integer[]> integers2 = Arrays.asList(arr2, arr3, arr4);
        System.out.println(integers2);//打印地址值


        //通过asList()方法转换过来的集合,有一个弊端,这个转换过来的集合,你不能改变这个集合的长度,
        // 也就是说,你不能再次增删集合中的元素。

        List<Integer> integers3 = Arrays.asList(100, 222, 777, 444);
        //integers3.add(222);//报错
       // integers3.remove(0);//报错
        
        //原因:
        
         /*   public static <T > List < T > asList(T...a){

            //这个方法的内部创建了一个 ArrayList
            //但是这个ArrayList 是Arrays里面的一个内部类,不是我们之前学的java.utli包下的ArrayList
            return new ArrayList<>(a);
        }*/


    }
}

8.二维数组

package org.westos.demo8;

import java.util.ArrayList;
import java.util.function.Consumer;

public class MyTest3 {
    public static void main(String[] args) {
        //二维数组
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("李白",22));
        list.add(new Student("杜甫",333));

        ArrayList<Student> list2 = new ArrayList<>();
        list2.add(new Student("苏轼",66));
        list2.add(new Student("苏洵",555));

        ArrayList<Student> list3 = new ArrayList<>();
        list3.add(new Student("纳兰容若",10));
        list3.add(new Student("龚自珍",9999));

        //把这三个list放在一个大集合中
        ArrayList<ArrayList<Student>> maxList  = new ArrayList<>();
        maxList.add(list);
        maxList.add(list2);
        maxList.add(list3);

        //遍历集合
        for (int i = 0; i < maxList.size(); i++) {
            ArrayList<Student> students = maxList.get(i);
            for (int j = 0; j < students.size(); j++) {
                Student student = students.get(j);
                System.out.println(student.getName()+"---"+student.getAge());
            }
            System.out.println();
        }

        for (ArrayList<Student> students : maxList) {
            for (Student student : students) {
                System.out.println(student.getName()+"---"+student.getAge());
            }
        }

        maxList.forEach(new Consumer<ArrayList<Student>>() {
            @Override
            public void accept(ArrayList<Student> students) {
                students.forEach(new Consumer<Student>() {
                    @Override
                    public void accept(Student student) {
                        System.out.println(student.getName()+"---"+student.getAge());
                    }
                });
            }
        });
    }
}

二、Set集合

无序性:存储数据和取出数据的顺序不一致.
唯一性:存储的元素不允许重复

1.HashSet

底层数据结构是哈希表,元素无序(存的顺序和取的顺序不一致),且不允许重复元素,
		可以存储null元素,线程不安全,效率高

(1)HashSet的无序性

HashSet存储元素是无序的
package org.westos.demo;

import java.util.HashSet;

public class MyTest {
    public static void main(String[] args) {
        //HashSet存储元素是无序的
        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(100);
        hashSet.add(300);
        hashSet.add(500);
        hashSet.add(700);
        hashSet.add(900);
        System.out.println(hashSet);
        }


}

(2)HashSet的唯一性

 HashSet 底层数据结构是哈希表. HashSet 不是线程安全的 集合元素可以是 null
​	 哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) (JDK1.7之前)


当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,
	然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
	HashSet 集合判断两个元素相等的标准:
	两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
	结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。

当我们往hashset集合存储对象的时候,会调用对象的hashCode方法,算出一个值,这个值就是确定这个对象放到表中的位置。
        那假如有两个对象,算出的位置值是一样的,就会调用equals()方法,去比较两个对象的地址值是否一样,如果一样证明证明是同一个对象.
        如果不一样那就存储进去,形成链表结构

        为了减少碰撞,我们应该合理的去重写hashCode方法,来减少碰撞(减少调用euquals方法的次数)尽量是元素在哈希表中横向排列,减少链表的形成

在这里插入图片描述

package org.westos.demo;

import java.util.HashSet;

public class MyTest2 {
    public static void main(String[] args) {
        //HashSet保证存储元素的唯一性
        HashSet<Student> hashSet = new HashSet<>();

        /*
        * 当向HashSet集合中存储元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,
	        根据hashCode值再计算出一个位置值,这个值就是存储的元素在集合中的位置
        * */
        hashSet.add(new Student("李白",22));
        hashSet.add(new Student("杜甫",26));
        hashSet.add(new Student("王维",27));
        hashSet.add(new Student("李白",20000));
        hashSet.add(new Student("李白",22));

        //此时的HashSet会存储重复元素,因为Student没有重写equals()方法和hashcode()方法
        System.out.println(hashSet);

        /*
        * 存储元素时,如果将Student类中的hashcode()方法的返回值设置为死值,那么所有对象的hashcode()方法
        * 的返回值都相同,这样就会带来一个问题,所有的对象都存储在一个位置,会造成碰撞次数过多
        *
        * 如何解决?
        *   原理:先调用hashcode方法计算hashCode值
        *       如果hashCode不同则表示不重复, 如果hashCode相同再调用equals方法进一步检查,
        *       equals返回真表示重复,否则表示不重复。
        *
        * 如何重写equals()方法?
        * 因为成员变量值影响了哈希值,所以我们把成员变量值相加即可
        *       如:
        *        return this.name.hashCode() + this.age;
		       这样存在缺陷
		        s1:name.hashCode()=40,age=30
		        s2:name.hashCode()=20,age=50
		       因此可以先比较hashCode值,再通过用equals方法进一步检查

        * */
    }
}

package org.westos.demo;

public class Student {
    private String name;
    private int age;

    @Override
    public int hashCode() {
        //这样会造成碰撞次数过多
        //return 0;
        return this.name.hashCode()+this.age;
    }



    @Override
    public boolean equals(Object obj){
        //这里比较地址值其实就是比较hash值
        if (this==obj){
            return true;
        }
        //判断obj是否是Studnet类的实例化对象
        if (!(obj instanceof Student)){
            return false;
        }
        Student s = (Student) obj;
        return this.name.equals(s.name) && this.age == s.age;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Student() {
    }
}

package org.westos.demo;

import java.util.HashSet;

public class MyTest3 {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        //Integer和String类型重写了hashcode()和equals()方法
        hashSet.add(100);
        hashSet.add(200);
        hashSet.add(300);
        hashSet.add(100);
        hashSet.add("aaa");
        hashSet.add("bbb");
        hashSet.add("ccc");
        hashSet.add("aaa");
        System.out.println(hashSet);
    }
}

(3)去重

构造一个包含指定 collection 中的元素的新 set。你把List集合传进来,构建一个HashSet集合,就帮你去重了
ArrayList<Integer> objects = new ArrayList<> ();
		objects.add (100);
		objects.add (200);
        objects.add (100);
        objects.add (200);
        HashSet<Integer> integers = new HashSet<> (objects);
        System.out.println (integers);

2.LinkedHashSet

   数据结构 有两个 链表和哈希表
​	 链表保证有序 哈希表保证元素唯一
LinkedHashSet集合的特点:元素有序 , 并且唯一
package org.westos.demo;

import java.util.Iterator;
import java.util.LinkedHashSet;

public class MyTest4 {
    public static void main(String[] args) {
        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(100);
        linkedHashSet.add(100);
        linkedHashSet.add(120);
        linkedHashSet.add(300);
        linkedHashSet.add(600);
        linkedHashSet.add(900);
        linkedHashSet.add(100000);
        Iterator<Integer> iterator = linkedHashSet.iterator();
        while (iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println(next);
        }
    }
}

3.TreeSet

TreeSet集合的特点: 元素唯一,并且可以对元素进行排序

在这里插入图片描述

TreeSet排序

排序:
a: 自然排序 使用的是无参构造

	要求元素实现Comparable这个接口重写compareTo()方法,根据比较的方法返回值的正负0 来决定元素在二叉树中放置的位置
	
注意:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素
必须实现Comparable接口 否则无法进行自然排序

Comparable接口中需要重写comparaTo方法, 保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等,则不重复存储

​	b: 使用比较器排序,使用有参构造
​	到底使用的是哪一种的排序取决于,构造方法.
(1)自然排序
使用无参构造
自然排序 使用的是无参构造

要求元素实现Comparable这个接口重写compareTo()方法,
	根据比较的方法返回值的正负0 来决定元素在二叉树中放置的位置

注意:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素
      必须实现Comparable接口 否则无法进行自然排序

      保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等
    		则不重复存储
package org.westos.demo3;

import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        //1.自然排序,必须实现Comparable接口,重写comparaTo方法,
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("李白",2222));
        treeSet.add(new Student("杜甫",333));
        treeSet.add(new Student("王维",443));
        treeSet.add(new Student("孟浩然",155));
        treeSet.add(new Student("苏轼",66));
        treeSet.add(new Student("欧阳修",66));
        treeSet.add(new Student("马飞飞",8888));
        treeSet.add(new Student("卢本伟",99999));
        System.out.println(treeSet);
    }
}
--------------------------
package org.westos.demo3;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    @Override
    public int compareTo(Student o) {
        //根据年龄进行排序

        //这样存在缺陷,只比较年龄不能说明是同一个对象
        //return this.age-o.age;

        int num= this.age-o.age;
        int num2=num==0?this.name.compareTo(o.name):num;

        return num2;

		//return -num2;
		
        //返回0表示相同,不用排序,也不用添加
        //return 0;
    }


}
-----------------------------
package org.westos.demo2;

import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Integer> treeSet = new TreeSet<>();
        //Integer默认重写了comparaTo方法
        treeSet.add(100);
        treeSet.add(200);
        treeSet.add(300);
        treeSet.add(400);
        treeSet.add(0);
        System.out.println(treeSet);
    }
}


按照姓名长度进行排序

package org.westos.demo4;



import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("李白",222));
        treeSet.add(new Student("杜甫",33));
        treeSet.add(new Student("王维",44));
        treeSet.add(new Student("孟浩然222",55));
        treeSet.add(new Student("苏轼sssssssssssssssss",66));
        treeSet.add(new Student("欧阳修aaaaaaa",66));
        treeSet.add(new Student("马飞飞",8888));
        treeSet.add(new Student("卢本伟",99999));
        for (Student student : treeSet) {
            System.out.println(student);
        }
    }
}
---------------------------------------------------------
package org.westos.demo4;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

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

    @Override
    public int compareTo(Student o) {
        //根据姓名长度进行排序

        int num=this.name.length()-o.name.length();

        int num2=num==0?this.name.compareTo(o.name):num;

        int num3=num2==0?(this.age-o.age):num2;

        return num3;
    }


}

(2)比较器排序
使用有参构造

 构造方法摘要
        TreeSet()
        构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。*/


       TreeSet(Comparator < ? super E > comparator)
        构造一个新的空 TreeSet,它根据指定比较器进行排序。*/
         Comparator 接口 强行对某个对象 collection 进行整体排序 的比较函数。

        采用比较器排序,根据比较器中的compare()这个方法的返回值的正负0 来决定元素在二叉树中放置的位置

package org.westos.demo5;

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

public class MyTest {
    public static void main(String[] args) {
    /*  构造方法摘要
        TreeSet()
        构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。*/

      /*  TreeSet(Comparator < ? super E > comparator)
        构造一个新的空 TreeSet,它根据指定比较器进行排序。*/
        // Comparator 接口 强行对某个对象 collection 进行整体排序 的比较函数。

        //采用比较器排序,根据比较器中的compare()这个方法的返回值的正负0 来决定元素在二叉树中放置的位置

        TreeSet<Integer> treeSet = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                //采用比较器排序,根据比较器中的compare()这个方法的返回值的正负0 来决定元素在二叉树中放置的位置
                return a-b;
            }
        });
        treeSet.add(100);
        treeSet.add(2);
        treeSet.add(30);
        treeSet.add(99999999);
        treeSet.add(1);
        treeSet.add(1);
        for (Integer integer : treeSet) {
            System.out.println(integer);
        }
    }
}

根据年龄和姓名长度进行排序

package org.westos.demo5;

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

public class MyTest2 {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student a, Student b) {
                //根据年龄大小进行排序
                return a.getAge()-b.getAge();

                //根据姓名的长度进行排序
                /*int num = a.getName().length() - b.getName().length();

                int num2=num==0?a.getName().compareTo(b.getName()):num;

                int num3=num2==0?a.getAge()-b.getAge():num2;
                return num3;*/
            }
        });
        treeSet.add(new Student("李白",222));
        treeSet.add(new Student("杜甫",33));
        treeSet.add(new Student("王维",44));
        treeSet.add(new Student("孟浩然222",55));
        treeSet.add(new Student("苏轼sssssssssssssssss",66));
        treeSet.add(new Student("欧阳修aaaaaaa",66));
        treeSet.add(new Student("马飞飞",8888));
        treeSet.add(new Student("卢本伟",99999));
        for (Student student : treeSet) {
            System.out.println(student);
        }
    }
}

案例一:
编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
			  并把最终的随机数输出到控制台。
			  选HashSet 可以不重复
			  选TreeSet 不重复还可以排序
package org.westos.demo6;

import java.util.Random;
import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        /*编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
        并把最终的随机数输出到控制台。
        选HashSet 可以不重复
        选TreeSet 不重复还可以排序*/
        TreeSet<Integer> treeSet = new TreeSet<>();

        Random random = new Random();
        while (treeSet.size()<10){
            int num = random.nextInt(20) + 1;
            treeSet.add(num);
        }
        for (Integer integer : treeSet) {
            System.out.println(integer);
        }
    }
}

案例二:
键盘录入3个学生信息(姓名, 语文成绩, 数学成绩, 英语成绩), 按照总分从高到低输出到控制台
package org.westos.demo6;

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

public class MyTest2 {
    public static void main(String[] args) {
        //键盘录入3个学生信息(姓名, 语文成绩, 数学成绩, 英语成绩), 按照总分从高到低输出到控制台
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student a, Student b) {
                double num=  (a.add()-b.add());
                double num2=num==0?a.getName().compareTo(b.getName()):num;
                //降序排列
               return (int) -num2;
            }
        });
        for (int i = 1; i <= 3; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入姓名");
            String name = sc.nextLine();
            System.out.println("请输入第"+i+"个学生的语文成绩");
            int ch = sc.nextInt();
            System.out.println("请输入第"+i+"个学生的数学成绩");
            int ma = sc.nextInt();
            System.out.println("请输入第"+i+"个学生的英语成绩");
            int en = sc.nextInt();
            //创建学生对象,把录入的信息,封装到学生学生对象里面
            Student student = new Student(name, ch, ma, en);
            treeSet.add(student);
        }
        for (Student student : treeSet) {
            System.out.println(student);
        }
//按照总分高低排序,输出学生的信息。
        System.out.println("名次\t姓名\t语文\t数学\t英语\t总分");
        int i=0;
        for (Student student : treeSet) {
            System.out.println((++i)+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore()+"\t"+student.add());
        }

    }
}

二.Map

1.Map集合概述和特点

键值映射:
    键---------值
	学号--------姓名
    s001-------张三
    s002-------李四
    s003-------王五
    
	A:
	Map接口概述
		查看API可以知道:
		将键映射到值的对象
		一个映射不能包含重复的键
		每个键最多只能映射到一个值
	B:
	Map接口和Collection接口的不同
		Map是双列的,Collection是单列的
		Map的键唯一,Collection的子体系Set是唯一的
		Map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
	C:
	Map集合 就是用来存储 这种 键值映射关系的数据 。 Map 是双列集合
        一个键只能只能映射一个值,键是唯一的。
       多次存储相同的键,就会发生键相同值覆盖。
       Map集合的数据结构只跟键有关,跟值没关系。
       Collection 单列集合
       存储键是String类型 值是Student类型
       HashMap 键的数据结构是哈希表,键的唯一性,要靠键重写hashCode()和equals()方法才能保证,如果不重写,则无法保证键的唯一性。
       String 类重写hashCode()和equals()方法

注意:
重写hashCode()和equals()方法后,如果键相同,会发生值覆盖.

在这里插入图片描述

package org.westos.demo;

import java.util.Collection;
import java.util.HashMap;
import java.util.function.BiConsumer;

public class MyTest {
    public static void main(String[] args) {
    /*    存储键是String类型,值是Student类型, HashMap 键的数据结构是哈希表,键的唯一性靠重写
        hashCode()和equals()方法才能保证,如果不重写,则无法保证键的唯一性。*/

        HashMap<String, Student> hashMap = new HashMap<>();
        //String默认重写了hashCode()和equals()方法
        //键相同,会发送值覆盖
       hashMap.put("aaa",new Student("李四",22));
       hashMap.put("bbb",new Student("李四",22));
       hashMap.put("aaa",new Student("李四",22));
       hashMap.put("aaa",new Student("李四",22));

        System.out.println(hashMap);
        System.out.println("===========================");
        HashMap<Student, String> hashMap2 = new HashMap<>();
        /*
        * 当Student没有重写hashCode()和equals()方法时,会存储重复元素,不能保证唯一性
        * 重写后,如果键相同,会发生值覆盖
        * */
        hashMap2.put(new Student("李白",22),"aaa");
        hashMap2.put(new Student("杜甫",33),"bbb");
        hashMap2.put(new Student("苏轼",44),"aaa");
        hashMap2.put(new Student("李白",22),"ccc");
        System.out.println(hashMap2);
    }
}

2.HashMap集合的功能

a:添加功能 
			V put(K key,V value):添加元素。这个其实还有另一个功能?替换
				如果键是第一次存储,就直接存储元素,返回null
				如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
		b:删除功能
			void clear():移除所有的键值对元素
			V remove(Object key):根据键删除键值对元素,并把值返回
		c:判断功能
			boolean containsKey(Object key):判断集合是否包含指定的键
			boolean containsValue(Object value):判断集合是否包含指定的值
			boolean isEmpty():判断集合是否为空
		d:获取功能
			Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
			V get(Object key):根据键获取值
			Set<K> keySet():获取集合中所有键的集合
			Collection<V> values():获取集合中所有值的集合
		e:长度功能
			int size():返回集合中的键值对的对数

(1)添加功能

package org.westos.demo;

import java.util.HashMap;

public class MyTest2 {
    public static void main(String[] args) {
       /*
       a:添加功能
       V put(K key,V value):添加元素。这个其实还有另一个功能?替换
        如果键是第一次存储,就直接存储元素,返回null
        如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值*/
        HashMap<Student, String> hashMap = new HashMap<>();
        String put = hashMap.put(new Student("李白", 100), "诗仙");
        System.out.println(put);//null
        String put1 = hashMap.put(new Student("杜甫", 200), "诗人");
        System.out.println(put1);//null
        String put2 = hashMap.put(new Student("杜甫", 200), "唐朝大诗人");
        System.out.println(put2);//诗人
        String put3 = hashMap.put(new Student("杜甫", 200), "石壕吏");
        System.out.println(put3);//唐朝大诗人

        System.out.println("--------------------------");
        HashMap<String, Student> hm = new HashMap<>();
        Student 李白 = hm.put("111", new Student("李白", 111));
        System.out.println(李白);//null
        Student 杜甫 = hm.put("222", new Student("杜甫", 222));
        System.out.println(杜甫);//null
        Student 王五 = hm.put("333", new Student("王五", 333));
        System.out.println(王五);//null
        Student 马飞 = hm.put("111", new Student("马飞", 999));
        System.out.println(马飞);//Student{name='李白', age=111}

        System.out.println(hm);//{111=Student{name='马飞', age=999}, 222=Student{name='杜甫', age=222},
                                // 333=Student{name='王五', age=333}}
    }
}

(2)删除功能

package org.westos.demo;

import java.util.HashMap;

public class MyTest3 {
    public static void main(String[] args) {
        HashMap<String, Student> hm = new HashMap<>();
        hm.put("aaa",new Student("张三",22));
        hm.put("bbb",new Student("李四",24));
        hm.put("ccc",new Student("王五",26));
        hm.put("aaa",new Student("张三",29));
        System.out.println(hm);
        System.out.println("=====================");
       /* b:删除功能
        void clear():移除所有的键值对元素
        V remove(Object key):根据键删除键值对元素,并把值返回*/

        //根据键来删除一对键值对 返回的是这个键所对应的的值

        Student ccc = hm.remove("ccc");
        System.out.println(ccc);
        System.out.println(hm);

        hm.clear();
        System.out.println(hm);
        System.out.println("==================================================");
        HashMap<Student, String> hm2 = new HashMap<>();
        hm2.put(new Student("张三",23),"111");
        hm2.put(new Student("李四",33),"222");
        hm2.put(new Student("王五",43),"444");
        hm2.put(new Student("张三",23),"999");
        System.out.println(hm2);

        String 李四 = hm2.remove(new Student("李四", 33));
        System.out.println(李四);
        String 王五 = hm2.remove(new Student("王五", 43));
        System.out.println(王五);
        System.out.println(hm2);
        hm2.clear();
        System.out.println(hm2);
    }
}


(3)判断功能

package org.westos.demo;

import java.util.HashMap;

public class MyTest4 {
    public static void main(String[] args) {
        /*c:判断功能
        boolean containsKey(Object key):判断集合是否包含指定的键
        boolean containsValue(Object value):判断集合是否包含指定的值
        boolean isEmpty():判断集合是否为空*/
        HashMap<String, Student> hm = new HashMap<>();
        hm.put("aaa",new Student("张三",22));
        hm.put("bbb",new Student("李四",24));
        hm.put("ccc",new Student("王五",26));
        hm.put("aaa",new Student("张三",29));
        boolean aaa = hm.containsKey("aaa");
        System.out.println(aaa);//true
        boolean 王五 = hm.containsValue(new Student("王五", 26));
        System.out.println(王五);//true
        boolean 张三 = hm.containsValue(new Student("张三", 22));
        System.out.println(张三);//false
        boolean empty = hm.isEmpty();
        System.out.println(empty);//false
        System.out.println("=======================");
        HashMap<Student, String> hm2 = new HashMap<>();
        hm2.put(new Student("张三",23),"111");
        hm2.put(new Student("李四",33),"222");
        hm2.put(new Student("王五",43),"444");
        hm2.put(new Student("张三",23),"999");
        System.out.println(hm2);
        boolean 张三2 = hm2.containsKey(new Student("张三", 23));
        System.out.println(张三2);//true
        boolean b = hm2.containsValue("444");
        System.out.println(b);//true
        boolean b1 = hm2.containsValue("111");
        System.out.println(b1);//false
        boolean empty1 = hm2.isEmpty();
        System.out.println(empty1);//false

    }
}

(4)获取功能

package org.westos.demo;

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

public class MyTest5 {
    public static void main(String[] args) {
        /*d:获取功能
        Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
        V get(Object key):根据键获取值
        Set<K> keySet():获取集合中所有键的集合
        Collection<V> values():获取集合中所有值的集合
        */
        HashMap<String, Student> hm = new HashMap<>();
        hm.put("aaa",new Student("张三",22));
        hm.put("bbb",new Student("李四",24));
        hm.put("ccc",new Student("王五",26));
        hm.put("aaa",new Student("张三",29));

        Student ccc = hm.get("ccc");
        System.out.println(ccc);
        Set<String> strings = hm.keySet();
        for (String string : strings) {
            System.out.println(string);
        }
        System.out.println("==========");
        Set<Map.Entry<String, Student>> entries = hm.entrySet();

        Collection<Student> values = hm.values();
        for (Student value : values) {
            System.out.println(value);
        }
         //获取集合中键值对的对数
        int size = hm.size();
        System.out.println(size);

    }
}

3.HashMap集合的遍历

A:键找值:
		获取所有键的集合
		遍历键的集合,获取到每一个键
		根据键找值
B:键值对对象找键和值思路:
		获取所有键值对对象的集合
		遍历键值对对象的集合,获取到每一个键值对对象
		根据键值对对象找键和值
C:
JDK1.8 提供的遍历方式forEach()方法
package org.westos.demo;

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

public class MyTest6 {
    public static void main(String[] args) {
        //HashMap集合的遍历

        //遍历方式1:通过键找值的方式来遍历
        HashMap<String, Student> hm = new HashMap<>();
        hm.put("aaa",new Student("张三",22));
        hm.put("bbb",new Student("李四",24));
        hm.put("ccc",new Student("王五",26));
        hm.put("aaa",new Student("张三",29));
        Set<String> strings = hm.keySet();//获取所有的键的集合
        System.out.println(strings);
        for (String key : strings) {
            Student value=hm.get(key);
            System.out.println(key+"===="+value);
        }
        System.out.println("=======================");
        //遍历方式2:键值对对象找键和值,
        // Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
        Set<Map.Entry<String, Student>> entries = hm.entrySet();
        for (Map.Entry<String, Student> entry : entries) {
            String key = entry.getKey();
            Student value = entry.getValue();
            System.out.println(key+"===="+value);
        }
        System.out.println("=======================");

        //遍历方式三:采用jdk1.8之后的forEach(方法)
        hm.forEach(new BiConsumer<String, Student>() {
            @Override
            public void accept(String key, Student value) {
                System.out.println(key+"===="+value);
            }
        });
    }
}

4.LinkedHashMap

A:LinkedHashMap的概述:	Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序
	B:LinkedHashMap的特点: 底层的数据结构是链表和哈希表 元素有序 并且唯一
				元素的有序性由链表数据结构保证 唯一性由 哈希表数据结构保证
				Map集合的数据结构只和键有关
		HashMap 键的数据结构是哈希表 保证键唯一,键无序
       LinkedHashMap 键的数据结构链表和哈希表。链表保证了键有序,哈希表保证了键唯一。


package org.westos.demo2;

import java.util.LinkedHashMap;

public class myTest {
    public static void main(String[] args) {
        //LinkedHashMap底层是哈希表和链表,保证元素的有序性和唯一性
        LinkedHashMap<String, Integer> lh = new LinkedHashMap<>();
        Integer aaa = lh.put("aaa", 111);
        System.out.println(aaa);//null
        Integer bbb = lh.put("bbb", 222);
        System.out.println(bbb);//null
        Integer ccc = lh.put("ccc", 333);
        System.out.println(ccc);//null
        lh.put("ccc",999);
        System.out.println(lh);
    }
}

5.TreeMap

TreeMap 键允许插入空值
		不允许插入null键,会抛 NullPointerException 异常;
			这样的话,程序健壮性不强,可以在排序时对其进行优化
			
	1.当未实现 Comparator 接口时,key 不可以为null,
		否则抛 NullPointerException 异常;

	2.当实现 Comparator 接口时,若未对 null 情况进行判断,则可能抛
			 NullPointerException 异常。如果针对null情况实现了,
			 可以存入,但是却不能正常使用get()访问,只能通过遍历去访问。


	A: TreeMap: 键的数据结构是红黑树,可保证键的排序和唯一性  
		    排序分为自然排序和比较器排序 
		    线程是不安全的效率比较高
排序:
package org.westos.demo2;

import java.util.TreeMap;

public class MyTest2 {
    public static void main(String[] args) {
        TreeMap<String, Student> treeMap = new TreeMap<>();
        //treeMap不允许存储null键
      treeMap.put("111",new Student("aaa",111));
      treeMap.put("222",new Student("bbb",222));
      treeMap.put("333",new Student("ccc",333));
        //treeMap允许存储null值
      treeMap.put("444",new Student(null,0));
        System.out.println(treeMap);

        //NullPointerException异常,这样的话,程序健壮性不强,可以在比较器排序时对其进行优化
        /*
        treeMap.put(null,new Student("连",22));
        System.out.println(treeMap);
        */
    }
}

package org.westos.demo2;

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


public class MyTest3 {
    public static void main(String[] args) {
        //1.自然排序,String类默认实现了Comparable接口,重写了compareTo方法
        // 仍然无法插入空键,程序报NullPointerException异常
        TreeMap<String, Student> treeMap = new TreeMap<>();
        treeMap.put("111",new Student("aaa",111));
        treeMap.put("222",new Student("bbb",222));
        treeMap.put("333",new Student("ccc",333));
       // treeMap.put(null,new Student("连",22));
        System.out.println(treeMap);

        //2.比较器排序
        TreeMap<String, Student> treeMap2 = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                Integer i = Integer.valueOf(a);
                Integer j = Integer.valueOf(b);
                return i-j;
            }
        });
        treeMap2.put("111",new Student("aaa",111));
        treeMap2.put("333",new Student("ccc",333));
        treeMap2.put("222",new Student("bbb",222));
        System.out.println(treeMap2);
    }
}

package org.westos.demo2;

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

public class MyTest4 {
    public static void main(String[] args) {
        //自然排序,需要键对应的类型实现Comparable接口,重写compareTo方法
        TreeMap<Student, Integer> treeMap = new TreeMap<>();
        treeMap.put(new Student("李白",22222),100);
        treeMap.put(new Student("成绩思涵",24),200);
        treeMap.put(new Student("武则天aaaaaaa",126),300);
        treeMap.put(new Student("疾风剑豪",28),400);

        System.out.println(treeMap);

        //比较器排序
        TreeMap<Integer, String> treeMap2 = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1-o2;
            }
        });
        treeMap2.put(100,"aaa");
        treeMap2.put(10,"bbb");
        treeMap2.put(30,"a");
        treeMap2.put(1,"mama");
        System.out.println(treeMap2);
        System.out.println("==================================");
        TreeMap<Student, Integer> treeMap3 = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student a, Student b) {
                //根据年龄进行比较
                int num=a.getAge()-b.getAge();
                int num2=num==0?a.getName().compareTo(b.getName()):num;
                return num2;

                //根据姓名进行比较
                /*int num=a.getName().length()-b.getName().length();

                int num2=num==0?a.getName().compareTo(b.getName()):num;

                int num3=num2==0?a.getAge()-b.getAge():num2;

                return num3;*/

            }
        });
        treeMap3.put(new Student("压缩",22),100);
        treeMap3.put(new Student("疾风剑豪",32),200);
        treeMap3.put(new Student("武则天aaaaaa",2),900);
        treeMap3.put(new Student("从",2),400);
        treeMap3.put(new Student("难道",2992),500);
        System.out.println(treeMap3);
    }
}


---------------------------------------------------------
package org.westos.demo2;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;

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

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    @Override
    public int compareTo(Student s) {
        //根据年龄进行排序
        /*int num=this.age-s.age;
        //如果年龄相同,不能认为是同一个对象,再去比较姓名
        int num2=num==0?this.name.compareTo(s.name):num;
        return num2;*/

        /*根据姓名排序
        * */
        int num=this.name.length()-s.name.length();

        int num2=num==0?this.name.compareTo(s.name):num;

        int num3=num2==0?this.age-s.age:num2;
        return num3;
    }
}


6.HashTable

HashMap  允许存储null值和null键  线程不安全 但是效率高
Hashtable  不允许存储null值和null键 线程安全 效率低
package org.westos.demo3;

import java.util.Hashtable;

public class MyTest {
    public static void main(String[] args) {
        Hashtable<String, Integer> hashtable = new Hashtable<>();
        hashtable.put("aaa",100);
        hashtable.put("bbb",200);
        hashtable.put("ccc",300);
        //报错,Hashtable不允许存null键和值
        hashtable.put(null,100);
    }
}

7.案例

1.	需求:随机输入一个字符串,统计字符串中每个字符出现的次数
			如:"aababcabcdabcde", 获取字符串中每一个字母出现的次数要求结果:a(5) b(4) c(3) d(2) e(1)
package org.westos.demo4;

import java.util.*;

public class MyTest {
    public static void main(String[] args) {
        //随机输入一个字符串,统计字符串中每个字符出现的次数
        //如:"aababcabcdabcde", 获取字符串中每一个字母出现的次数要求结果:a(5) b(4) c(3) d(2) e(1)
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String s = sc.nextLine();

        //定义hashmap存储字符和出现次数
        HashMap<Character, Integer> hashMap = new HashMap<>();
             Character c=' ';
        for (int i = 0; i < s.length(); i++) {
             c = s.charAt(i);
            if (!hashMap.containsKey(c)){
                //不包含字符,就将该字符当作键,值为1存储;
                hashMap.put(c,1);
            }
            if (hashMap.containsKey(c)){
                hashMap.put(c,hashMap.get(c)+1);
            }
        }
        System.out.println(hashMap);

    }
}

2.集合嵌套之HashMap嵌套HashMap
基础班
	张三	20
	李四	22
就业班
	王五	21
	赵六	23
package org.westos.demo5;

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

public class MyTest {
    public static void main(String[] args) {
      /*  集合嵌套之HashMap嵌套HashMap
                基础班
                    张三	20
                    李四	22
                就业班
                    王五	21
                    赵六	23*/
        HashMap<String, Integer> hashMap = new HashMap<>();
        hashMap.put("张三",20);
        hashMap.put("李四",22);
        HashMap<String, Integer> hashMap1 = new HashMap<>();

        hashMap1.put("王五",21);
        hashMap1.put("赵六",23);

        HashMap<String, HashMap<String, Integer>> hashMap2 = new HashMap<>();
        hashMap2.put("基础班",hashMap);
        hashMap2.put("就业班",hashMap1);
        System.out.println(hashMap2);

        Set<Map.Entry<String, HashMap<String, Integer>>> entries = hashMap2.entrySet();
        for (Map.Entry<String, HashMap<String, Integer>> entry : entries) {
            String key = entry.getKey();
            System.out.println(key);
            HashMap<String, Integer> value = entry.getValue();
            Set<Map.Entry<String, Integer>> entries1 = value.entrySet();
            for (Map.Entry<String, Integer> stringIntegerEntry : entries1) {
                String key1 = stringIntegerEntry.getKey();
                Integer value1 = stringIntegerEntry.getValue();
                System.out.println("\t"+key1+"\t"+value1);
            }
            System.out.println();
        }
    }
}

3.集合嵌套之HashMap嵌套ArrayList
三国演义
 	吕布
 	周瑜
 笑傲江湖
 	令狐冲
 	林平之
 神雕侠侣
 	郭靖
 	杨过  
package org.westos.demo6;

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

public class MyTest {
    public static void main(String[] args) {
        /*
        * 三国演义
		 	吕布
		 	周瑜
		 笑傲江湖
		 	令狐冲
		 	林平之
		 神雕侠侣
		 	郭靖
		 	杨过  */
        ArrayList<String> strings = new ArrayList<>();
        strings.add("吕布");
        strings.add("周瑜");
        ArrayList<String> strings2 = new ArrayList<>();
        strings2.add("令狐冲");
        strings2.add("林平之");
        ArrayList<String> strings3 = new ArrayList<>();
        strings3.add("郭靖");
        strings3.add("杨过");

        HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
        hashMap.put("三国演义",strings);
        hashMap.put("笑傲江湖",strings2);
        hashMap.put("神雕侠侣",strings3);

        //遍历hashmap
        Set<Map.Entry<String, ArrayList<String>>> entries = hashMap.entrySet();
        for (Map.Entry<String, ArrayList<String>> entry : entries) {
            String key = entry.getKey();
            System.out.println(key);
            ArrayList<String> value = entry.getValue();
            for (String s : value) {
                System.out.println("\t"+s);
            }
            System.out.println();
        }

    }
}

4.集合嵌套之ArrayList嵌套HashMap
		
		假设ArrayList集合的元素是HashMap。有3个。
		每一个HashMap集合的键和值都是字符串。
	
		 周瑜---小乔
		 吕布---貂蝉
	
		 郭靖---黄蓉
		 杨过---小龙女
	
		 令狐冲---任盈盈
		 林平之---岳灵珊
package org.westos.demo6;

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

public class MyTest2 {
    public static void main(String[] args) {
        /*集合嵌套之ArrayList嵌套HashMap

        假设ArrayList集合的元素是HashMap。有3个。
        每一个HashMap集合的键和值都是字符串。

        周瑜---小乔
        吕布---貂蝉

        郭靖---黄蓉
        杨过---小龙女

        令狐冲---任盈盈
        林平之---岳灵珊*/
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("周瑜","小乔");
        hashMap.put("吕布","貂蝉");
        HashMap<String, String> hashMap2 = new HashMap<>();
        hashMap2.put("郭靖","黄蓉");
        hashMap.put("杨过","小龙女");
        HashMap<String, String> hashMap3 = new HashMap<>();
        hashMap.put("令狐冲","任盈盈");
        hashMap.put("林平之","岳灵珊");

        ArrayList<HashMap<String, String>> arrayList = new ArrayList<>();
        arrayList.add(hashMap);
        arrayList.add(hashMap2);
        arrayList.add(hashMap3);

        for (HashMap<String, String> stringStringHashMap : arrayList) {
            Set<Map.Entry<String, String>> entries = stringStringHashMap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                System.out.println("\t"+key+"==="+"\t"+value);
            }
            System.out.println();
        }
    }
}

8.Collections工具类

A:
它是集合的工具类,所有的方法都是静态方法,可以直接类名调方法
B:
常见方法:
public static < T > void sort(List< T > list):按照自然顺序排序集合
public static < T> int binarySearch(List< ? > list,T key):二分法查找。
public static < T > T max(Collection< ? > coll):获取集合中的最大值
public static void reverse(List< ? > list):反转集合
public static void shuffle(List< ? > list):随机打乱集合

斗地主案例
package org.westos.demo8;

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

public class MyTest {
    public static void main(String[] args) {
        //斗地主案例
        //先创建两个可以组成52张牌的集合
        String []shape={"♠","♥","♦","♣"};
        String [] num={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        //建立集合存储牌
        ArrayList<String> list = new ArrayList<>();
        //将牌放进list集合
        for (String s1 : num) {
            for (String s2 : shape) {
                String s = s1.concat(s2);
                list.add(s);
            }
        }
        list.add("☀");//大王
        list.add("☼");//小王

        //洗牌
        Collections.shuffle(list);
        Collections.shuffle(list);
        Collections.shuffle(list);

        //需要三个玩家参与斗地主,还得留三张底牌
        ArrayList<String> palyer1 = new ArrayList<>();
        ArrayList<String> palyer2 = new ArrayList<>();
        ArrayList<String> palyer3 = new ArrayList<>();
        ArrayList<String> diPai = new ArrayList<>();

        //发牌方式1: 一人数个10来张发给你
        //palyer1 = (ArrayList<String>) list.subList(0, 11);


        // 方式2:传统发牌 一人一张转着发
        //用牌的索引对3取余
      /* 玩家1   0 3 6 9   余数 0
        玩家2   1 4 7 10  余数 1
        玩家3   2 5 8  11  余数 2 */

        for (int i = 0; i < list.size(); i++) {
            if (i>=list.size()-3){
                diPai.add(list.get(i));
            }else if (i%3==0){
                palyer1.add(list.get(i));
            }else if (i%3==1){
                palyer2.add(list.get(i));
            }else if (i%3==2){
                palyer3.add(list.get(i));
            }
        }
 	 //做一个斗地主排序版,牌发好之后,从小到大排好
        Collections.sort(palyer1);
        Collections.sort(palyer2);
        Collections.sort(palyer3);
        //看牌
        see("卢本伟",palyer1);
        see("马飞飞",palyer2);
        see("阿姨",palyer3);
       

    }
    public static void see(String name, ArrayList<String> list){

        for (String poker : list) {
            System.out.print(poker+"\t");
        }
        System.out.println();
    }
}

斗地主有序版
package org.westos.demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        //创建一个hashmap,键为索引,值为牌,用来存储牌
        HashMap<Integer, String> hm = new HashMap<>();

        String []shape={"♠","♥","♦","♣"};
        String [] num={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};

        //创建一个单列集合,存放牌的索引
        ArrayList<Integer> list = new ArrayList<>();

        int index = 0;
        //往牌盒里存储牌
        //注意外层num,内存shape
            for (String str : num) {
                for (String s : shape) {
                hm.put(index,s.concat(str));
                //把索引放在索引集合中
                list.add(index);
                index++;
            }
        }
        System.out.println(index);

        //手动添加大小王
        hm.put(index,"●");
        list.add(index);
        index++;
        hm.put(index, "○");
        list.add(index);

        //洗牌,洗的是索引集合
        Collections.shuffle(list);

        //发牌,要有序,用TreeSet集合
        TreeSet<Integer> 卢本伟 = new TreeSet<>();
        TreeSet<Integer> 马飞飞 = new TreeSet<>();
        TreeSet<Integer> 卡布奇诺阿姨 = new TreeSet<>();
        TreeSet<Integer> 底牌 = new TreeSet<>();
        for (int i = 0; i < list.size(); i++) {
            //留底牌
            if (i >= list.size() - 3) {
                底牌.add(list.get(i));
            } else if (i % 3 == 0) {
                卢本伟.add(list.get(i));
            } else if (i % 3 == 1) {
                马飞飞.add(list.get(i));
            } else {
                卡布奇诺阿姨.add(list.get(i));
            }
        }
        //看牌
        look("卢本伟",卢本伟,hm);
        look("马飞飞",马飞飞,hm);
        look("卡布奇诺阿姨",卡布奇诺阿姨,hm);
        look("底牌",底牌,hm);

    }
    private static void look(String name,TreeSet<Integer> treeSet,HashMap<Integer, String> hm){
        System.out.println(name);
        for (Integer key : treeSet) {
            String value = hm.get(key);
            System.out.print(value+"\t");
        }
        System.out.println();
    }


}


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值