Java笔记--集合(持有对象)

生非贵之所能存,身非爱之所能厚;生亦非贱之所能夭,身亦非轻之所能薄。

                                                                                                                                        --列子

Java中的容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:

Collection:

一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入的顺序保存元素,而Set中不能有相同的元素。Queue按照排队的规则来确定对象产生的顺序(通常与它们被插入的顺序相同)。

Map:

一组成对的“键值对”对象,允许你使用键来进行查找值。ArrayList允许你使用数字来查找值,因此在某种意义上讲,它将数字和对象进行了关联。映射表允许我们使用另一对象来查找某个对象,它也被称为“关联数组”,因为它将某些对象与另一些对象关联在一起;或者被称为”字典“,因为你可以使用键对象来查找对值对象,就像在字典中使用单词来定义一样。

图解:

一、Collection接口

        Collection :集合层次结构中的根界面。集合表示一组被称为其元素的对象。一些集合允许重复元素,而其他集合不允许。

        通过观察api发现,Collection一个接口,我们无法直接对其创建对象,要想使用Collection接口中的方法,应该寻找一个它具体实现的子类

        利用这个子类对象,来使用Collection中的方法。

        通过api介绍我们又能够知道Collection是单元素集合的顶层接口,它相关的集合有些可以元素重复,有些不可以。

        Collection又向下分了两种类型的集合:List(元素可以发生重复的)和Set(元素唯一)

        Collection(接口)

                -List(接口)

                ArrayList(具体实现子类)

                -Set(接口)

        我们找到了Collection中其中一个实现子类:ArrayList,我们借助创建该类的对象,来学习并使用Collection接口中的方法

        我们使用ArrayList的无参构造方法来实现创建

Collection成员方法:

boolean add(E e)
boolean remove(Object o)
void clear()
boolean contains(Object o)
boolean isEmpty()
int size()

package day12;

/*
    Collection:合层次结构中的根界面 。 集合表示一组被称为其元素的对象。 一些集合允许重复元素,而其他集合不允许。 】、
    有些被命令和其他无序。 JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如Set和List
    通过观察api发现,Collection是一个接口,我们无法直接对其创建对象,要想使用Collection接口中的方法,应该找一个它具体的实现子类
    利用这个实现子类对象,来使用Collection中的方法。

    通过api介绍我们又能够知道Collection是单元素集合的顶层接口,它相关的集合有些可以元素重复,有些不可以。
    Collection又向下分了两种类型的集合:List(元素可以发生重复)和Set(元素唯一)

    Collection(接口)
        - List(接口)
            ArrayList(具体实现子类)
        - Set(接口)


    我们找到了Collection中其中一个实现子类:ArrayList,我们借助创建该类的对象,来学习并使用Collection接口中的方法
    我们可以使用ArrayList的无参构造方法来创建

    Collection成员方法:
        boolean add(E e)
        boolean remove(Object o)
        void clear()
        boolean contains(Object o)
        boolean isEmpty()
        int size()


 */

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

public class CollectionDemo1 {
    public static void main(String[] args) {
        Collection c1 = new ArrayList();


        System.out.println("c1:"+c1);//重写的toString()方法来自AbstractCollection类中
        System.out.println("============================");
        //boolean add(Object e)向集合中添加元素
        c1.add("hello");
        c1.add(true);
        c1.add(11.23);
        c1.add(100);
        c1.add('c');
        c1.add(10000L);
        System.out.println("c1: "+c1);

        //boolean remove(Object o)从集合中删除某个元素
//        c1.remove(100);//若删除的元素有重复的存在,只会删除最左边的第一个相同元素
//        System.out.println("c1: "+c1);

        //void clear()清空集合中的所有的元素
//        c1.clear();
//        System.out.println("c1: "+c1);

        //boolean contains(Object o)判断集合中是否包含某个元素
        System.out.println(c1.contains("hello"));
        
        //boolean isEmpty()判断集合中是否有元素存在着
        System.out.println(c1.isEmpty());

        //int size() 获取集合中的元素个数
        System.out.println(c1.size());
    }
}

 Collection中的成员方法:

boolean addAll(Collection c)
boolean removeAll(Collection c)
boolean containsAll(Collection c)
boolean retainAll(Collection c)

package day12;

/*
    Collection中的成员方法:
        boolean addAll(Collection c)
        boolean removeAll(Collection c)
        boolean containsAll(Collection c)
        boolean retainAll(Collection c)

    今后我们在开发中,一个集合只能存储一种数据类型的元素。
 */

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

public class CollectionDemo2 {
    public static void main(String[] args) {
        Collection c1 = new ArrayList();
        c1.add("hello");
        c1.add("world");
        c1.add("java");
        c1.add("hadoop");
        c1.add("hello");

        Collection c2 = new ArrayList();
        c2.add("hello");
        c2.add("hadoop");
        c2.add("nihao");

        Collection c3 = new ArrayList();
        c3.add("hello");
        c3.add("hadoop");

        System.out.println("c1: "+c1);
        System.out.println("c2: "+c2);
        System.out.println("c3: "+c3);

//        System.out.println("============================");
        //boolean addAll(Collection c)将直接添加另一个集合中所有单元素
//        c1.addAll(c2);
//        System.out.println("c1: "+c1);
//        System.out.println("c2: "+c2);

        //boolean removeAll(Collection c)从一个集合中移除另一个集合中所有的元素
//        c1.removeAll(c2);
//        System.out.println("c1: "+c1);
//        System.out.println("c2: "+c2);

        //boolean containsAll(Collection c)判断集合A中是否包含集合B所有元素
//        System.out.println(c1.containsAll(c2));
//        System.out.println(c1.containsAll(c3));

        System.out.println("============================");
        //boolean retainAll(Collection c)A集合和B集合做交集,重复的部分覆盖到A集合中,B集合不变
        c1.retainAll(c2);
        System.out.println("c1: "+c1);
        System.out.println("c2: "+c2);
    }
}

 二、Inerator接口

Collection集合如何遍历

 学习集合的4个步骤:
        1、如何创建集合对象?
        2、如何创建元素对象?
        3、如何将元素对象添加到集合中?
        4、如何遍历集合?

package day12;

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

public class CollectionDemo3 {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection c1 = new ArrayList();

        //创建元素、添加元素
        c1.add("hello");
        c1.add("java");
        c1.add("world");
        c1.add("hello");
        c1.add("hadoop");

        //遍历集合
        //方式1:Object[] toArray() 把集合转成数组,可以实现集合的遍历
        Object[] arr1 = c1.toArray();
        for (int i = 0; i < arr1.length; i++) {
            Object o = arr1[i];//Object o = "hello"
            String s = (String)o;
            System.out.println(s + "," + s.length());
        }

        //方式2:Iterator iterator()迭代器遍历,Collection集合的专用遍历方式
        //调用Collection接口中的iterator()方法获取集合对应的迭代器对象
        //迭代器对象中存储了集合中每一个元素,Iterator类中有方法可以给我们使用获取元素对象
        Iterator iterator = c1.iterator();//Iterator iterator = new Itr()
        //通过观察源码发现,Itr类中只有next方法有返回值是Object类型的,该方法就是获取元素的方法
//        Object o = iterator.next();//Object o = "hello"
//        System.out.println(o);
//        Object o1 = iterator.next();
//        System.out.println(o1);
//        Object o2 = iterator.next();
//        System.out.println(o2);
//        Object o3 = iterator.next();
//        System.out.println(o3);
//        Object o4 = iterator.next();
//        System.out.println(o4);
//        Object o5 = iterator.next();
//        System.out.println(o5);

        //我们应该在next方法调用之前,先看一看迭代器中下一个位置上是否有元素,若有元素,才能进行调用
        //Iterator接口中提供了一个方法hasNext(),帮助我们判断下一个位置上是否有元素
        while(iterator.hasNext()){
            Object o = iterator.next();
            System.out.println(o);
        }
        System.out.println("==============================");
        while(iterator.hasNext()){
            Object o = iterator.next();
            System.out.println(o);
        }//第二次发现没有放回值,是因为迭代器的底层逻辑问题。迭代器遍历只能使用一次
    }
}

Iterator接口成员方法:

boolean hasNext()

E next()

package cday12;

/*
    存储自定义对象并遍历
    Student(name,age)
*/

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

public class CollectionDemo4 {
    public static void main(String[] args) {
        //1、创建Collection集合对象
        Collection c1 = new ArrayList();

        //2、创建元素对象
        Student s1 = new Student("小花", 3);
        Student s2 = new Student("小白", 5);
        Student s3 = new Student("小黑", 6);
        Student s4 = new Student("小黄", 2);

        //3、将元素对象添加到集合中去
        c1.add(s1);
        c1.add(s2);
        c1.add(s3);
        c1.add(s4);

        //4、遍历集合
        //方式1:转数组再遍历
        Object[] array = c1.toArray();
        for (int i = 0; i < array.length; i++) {
            Object o = array[i];//Object o = new Student("小花",3)
            Student s = (Student)o;
            System.out.println("姓名:" + s.getName() + ", 年龄:" + s.getAge());
        }
        System.out.println("-------------------------------");
        //方式2:迭代器遍历
        Iterator iterator = c1.iterator();
        while(iterator.hasNext()){
            Object o = iterator.next();
            Student s = (Student) o;
            System.out.println("姓名:" + s.getName() + ", 年龄:" + s.getAge());
        }
    }
}

三、List接口

需求:

        使用List集合存储字符串元素,使用迭代器遍历,遍历的时候,如果遇到"java",就向集合中添加一个元素"shujia"

package day13;

/*
    需求:
        使用List集合存储字符串元素,使用迭代器遍历,遍历的时候,如果遇到"java",就向集合中添加一个元素"shujia"

    我们按照需求编写代码,在遍历迭代器的时候,当遇到"java",我们是使用集合中add方法进行添加元素的,运行的时候就报错了
    ConcurrentModificationException 并发修改异常,迭代器遍历的时候,无法使用集合的方法对集合本身做改动。

 */

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

public class ListDemo1 {
    public static void main(String[] args) {
        List list1 = new ArrayList();

        list1.add("hello");
        list1.add("java");
        list1.add("hadoop");
        list1.add("redis");
        System.out.println("list1: " + list1);

//        Iterator iterator = list1.iterator();
//        while(iterator.hasNext()){
//            Object o = iterator.next();
//            String s = (String) o;
//            if("java".equals(s)){
//                list1.add("shujia");
//            }
//        }

        //因为继承自父亲的迭代器中没有添加元素的方法,所有我们需要使用List中特有的迭代器进行遍历及添加
        //通过观察源码发现,List中特有的迭代器中的add方法,不仅可以对迭代器中的元素进行添加,底层也针对原集合进行添加元素
        //将原集合以及迭代器的版本号也设置成一样的了,所以将来再检查版本号的时候,原集合和迭代器的版本号是一样的
        //这样就不会产生并发修改异常了
        ListIterator listIterator = list1.listIterator();
        while(listIterator.hasNext()){
            Object o = listIterator.next();
            String s = (String) o;
            if("java".equals(s)){
                listIterator.add("hello world");
            }
        }

        System.out.println(list1);

        Object[] array = list1.toArray();
        for (int i = 0; i < array.length; i++) {
            String s = (String) array[i];
            if ("java".equals(s)){
                list1.add("hello world");
            }
        }

        System.out.println("list1: "+list1);
    }
}
package day13;

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

public class ListDemo2 {
    public static void main(String[] args) {
        List list1 = new ArrayList();

        Iterator iterator = list1.iterator();

        list1.add("hello");
        list1.add("java");
        list1.add("hadoop");
        list1.add("redis");

        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("list1: "+list1);
    }
}

四、ArrayList类(List接口)

ArrayList:底层数据结构是数组,查询快、增删慢,线程不安全的,效率高

/*
        Collection:
            - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复,且有索引的概念)
                - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高。
                - Vector
                - LinkedList
            - Set(元素唯一且无序)
 */

package day13;

import java.util.ArrayList;
import java.util.Iterator;

/*
        Collection:
            - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复,且有索引的概念)
                - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高。


                - Vector
                - LinkedList
            - Set(元素唯一且无序)
 */
public class ArrayListDemo1 {
    public static void main(String[] args) {
        //存储字符串并遍历
        ArrayList list1 = new ArrayList();

        list1.add("hello");
        list1.add("world");
        list1.add("java");
        list1.add("apple");
        list1.add("hello");

        Iterator iterator = list1.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
}

 例题:

(1)去除集合中字符串的重复值(字符串内容相同)

package day13;
import java.util.ArrayList;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList list1 = new ArrayList();

        list1.add("java");
        list1.add("hadoop");
        list1.add("hive");
        list1.add("java");
        list1.add("hello");
        list1.add("hadoop");

        System.out.println("list1: " + list1);

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

        ArrayList list2 = new ArrayList();
        for (int i = 0; i < list1.size(); i++) {
            String s = (String)list1.get(i);
            if (!list2.contains(s)){
                list2.add(s);
            }
        }
        System.out.println("list2: "+list2);
    }
}

 (2)去除集合中自定义对象的重复值(对象的成员变量值都相同)

自定义:student类

package day13;

import java.util.Objects;

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

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + 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);
    }
}

测试类:ArrayListTest类

package day13;/

import java.util.ArrayList;


public class ArrayListTest2 {
    public static void main(String[] args) {
        ArrayList list1 = new ArrayList();

        Student s1 = new Student("小黑", 18);
        Student s2 = new Student("小白", 17);
        Student s3 = new Student("小花", 18);
        Student s4 = new Student("小红", 19);
        Student s5 = new Student("小黑", 18);

        list1.add(s1);
        list1.add(s2);
        list1.add(s3);
        list1.add(s4);
        list1.add(s5);

        System.out.println("list1: " + list1);

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

        ArrayList list2 = new ArrayList();
        for (int i = 0; i < list1.size(); i++) {
            Student s = (Student) list1.get(i);
            if (!list2.contains(s)){
                list2.add(s);
            }
        }
        System.out.println("list2: "+list2);
    }
}

五、Vector类(List接口)

Vetcor:底层数据结构式数组,查询快,增删慢,线程安全的,效率低;

Collection:
        - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复,且有索引的概念)
            - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高。
            - Vector:底层数据结构是数组,查询快,增删慢,线程安全的,效率低
                【即便Vector是线程安全的,我们今后也不用,我们会将不安全的ArrayList变成安全的】

            - LinkedList:
        - Set(元素唯一且无序)

Vector类中的特有功能:
    public void addElement(E obj)
    public E elementAt(int index)
    public Enumeration elements()

package com.shujia.day13;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

/*
        Collection:
        - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复,且有索引的概念)
            - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高。
            - Vector:底层数据结构是数组,查询快,增删慢,线程安全的,效率低
                【即便Vector是线程安全的,我们今后也不用,我们会将不安全的ArrayList变成安全的】
            - LinkedList:
        - Set(元素唯一且无序)

 Vector类中的特有功能:
    public void addElement(E obj)
    public E elementAt(int index)
    public Enumeration elements()

 */
public class VectorDemo1 {
    public static void main(String[] args) {
        Vector vector = new Vector();

        vector.add("hello");
        vector.add("world");
        vector.add("java");
        vector.add("hadoop");
        vector.add("hello");

        vector.addElement("flink"); // 从效果上来看和调用add方法一样,都是在集合的末尾处添加元素,将来就使用add来替代它

        Iterator iterator = vector.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("==============================");
        //public E elementAt(int index) 根据索引获取元素
        System.out.println(vector.elementAt(2)); // 从效果上来看和调用get方法一样,都是根据索引获取元素,将来就使用get来替代它
        System.out.println(vector.get(2));
        System.out.println("==============================");
        //public Enumeration elements() 获取一个存储所有集合元素的容器,类似于迭代器
        // 从效果上来看和使用迭代器一样,都是先判断下一个位置是否有元素,然后再获取,将来就使用迭代器来替代它
        Enumeration elements = vector.elements();
        while (elements.hasMoreElements()){
            Object o = elements.nextElement();
            System.out.println(o);
        }


    }
}

六、LinkedList类(List接口)

LinkedList:底层数据结构是双链表,增删快,查询慢,线程不安全的,效率高。

Collection:
        - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复,且有索引的概念)
            - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高。
            - Vector:底层数据结构是数组,查询快,增删慢,线程安全的,效率低
                【即便Vector是线程安全的,我们今后也不用,我们会将不安全的ArrayList变成安全的】
            - LinkedList:底层数据结构是双链表,增删快,查询慢,线程不安全的,效率高。
        - Set(元素唯一且无序)

     LinkedList类特有功能:

public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()

package day13;

import java.util.Iterator;
import java.util.LinkedList;

public class LinkedListDemo1 {
    public static void main(String[] args) {
        LinkedList list1 = new LinkedList();

        list1.add("hello");
        list1.add("world");
        list1.add("java");
        list1.add("hadoop");
        list1.add("hello");

        System.out.println(list1);

        System.out.println("====================");
        list1.addFirst("小花");
        list1.addLast("小胡");//add
        System.out.println(list1);


        System.out.println("===========================");
        System.out.println(list1.getFirst());
        System.out.println(list1.getLast());


        System.out.println("================================");
        System.out.println(list1.removeFirst());
        System.out.println(list1.removeLast());
        System.out.println(list1);


    }
}

案例:

请用LinkedList模拟栈数据结构的集合,并测试(栈:先进后出)

定义类:MyStack类

package day13;

import java.util.LinkedList;

public class MyStack {
    private LinkedList linkedList;

//    public MyStack(LinkedList linkedList) {
//        this.linkedList = linkedList;
//    }

    public MyStack() {
        linkedList = new LinkedList();
    }

    public void Add(Object obj){
        linkedList.addFirst(obj);
    }

    public int stackSize(){
        return linkedList.size();
    }

    public Object getObject(){
        //return linkedList.getFirst();错误:模拟的是栈,栈中的内容弹出后不会留下值,所以不是get方法,要用remove方法,同步删除数据
        return linkedList.removeFirst();
    }

    @Override
    public String toString() {
        return "MyStack{" +
                "linkedList=" + linkedList +
                '}';
    }
}

测试类:LinkedListTest1类

package day13;
/*
    LinkedList
    请用LinkedList模拟栈数据结构的集合,并测试
    栈:先进后出

    题目的要求是:自己创建一个类,将LinkedList作为成员变量,将来创建自己的类对象,使用自己的方法,但是底层用的是LinkedList中的方法

 */
public class LinkedListTest1 {
    public static void main(String[] args) {
//        LinkedList list1 = new LinkedList();
//
//        list1.add("hello");
//        list1.add("world");
//        list1.add("java");
//        list1.add("hadoop");
//        System.out.println("list1: " + list1);
//
//        System.out.println("----------------------------------");
//        for (int i = list1.size() - 1; i >= 0; i--) {
//            System.out.println(list1.remove(i));
//        }

        /*
            如果按照上面的做法解题,0分。
         */
        MyStack myStack = new MyStack();
        myStack.Add("hello");
        myStack.Add("world");
        myStack.Add("java");
        myStack.Add("hadoop");
        System.out.println(myStack);
        System.out.println("===========================");

        for (int i = myStack.stackSize() - 1; i >= 0; i--) {
            System.out.println(myStack.getObject());
        }
    }
}

七、增强for的概述及使用

语句定义格式:

        for(元素的类型 变量名 : Collection集合|数组){

                直接使用变量,就相当于使用元素

        }

 注意事项:

1. 增强for循环本质用来替代迭代器的
2. 数组也蹭了增强for循环的光

package day14;

import java.util.ArrayList;
import java.util.Iterator;

public class ForDemo1 {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();//自动类型推断

        list1.add("hello");
        list1.add("world");
        list1.add("java");
        list1.add("hadoop");
        list1.add("hello");
        list1.add("java");

        //方式1:转数组遍历
        Object[] array = list1.toArray();
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
        System.out.println("===========================");

        //方式2:迭代器遍历
        Iterator<String> iterator = list1.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("==============================");

        //方式3:for循环,因为List集合有索引,所以有第三中方式遍历,使用size()和get()
        for (int i = 0; i < list1.size(); i++) {
            System.out.println(list1.get(i));
        }
        System.out.println("======================================");

        /*
        * 方式4:使用增强for循环遍历Collection集合或数组,增强for循环本质是用来替代迭代器的
        *
        * 语句定义格式:
        *   for(元素的类型 变量名:Collection集合|数组){
        *       直接使用变量,就相当于使用元素
        * }
        *
        * 注意事项:
        * 1、增强for循环本质用来替代迭代器的
        * 2、数组也可以使用增强for循环的功能
        * */

//        for(String s: list1){
//            if ("java".equals(s)){//
//                list1.add("xxxxx");
//            }
//            System.out.println(s);
//        }


        System.out.println("============================");
        String[] arr = {"das","daeqwes","hello","world"};
        for(String s: arr){
            System.out.println(s);
        }
        System.out.println("====================================");

        list1.forEach(System.out::println); // lambda表达式的简化写法

//        list1.forEach((e)->{
//            String upperCase = e.toUpperCase();
//            System.out.println(upperCase);
//        });
    }
}

八、可变参数概述及使用

可变参数:

在方法定义的时候,指名该方法某个数据类型可以传入若干个

注意:

Java中方法的可变参数只能定义在最后一个,一个方法只能有一个可变参数

package day14;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

public class CanshuDemo1 {
    public static void main(String[] args) {
        //需求1:定义一个方法,求两个int类型元素和
        System.out.println(sum(10,20));

        //需求2:定义一个方法,求三个int类型元素的和
        System.out.println(sum(10, 20, 30));

        //需求3: 定义一个方法,求四个int类型元素的和
        System.out.println(sum(10, 20, 30, 40));

        //需求4: 定义一个方法,求五个int类型元素的和
        System.out.println(sum(10, 20, 30, 40, 50));

        //需求5: 现在有一个姓名字符串和若干个分数,求该学生的总分
        fun1("张三", 98, 90, 10);
//        fun2(98, 90, 10, "魏一民");
    }

//    public static void fun1(int... scores,String name) {
//        int sum = 0;
//        for (int i : scores) {
//            sum += i;
//        }
//        System.out.println(name + "的考试总分为: " + sum);
//    }

    public static void fun1(String name, int... scores) {
        int sum = 0;
        for (int i : scores) {
            sum += i;
        }
        System.out.println(name + "的考试总分为: " + sum);
    }
    
    public static int sum(int... ints){
        //int... 表示方法调用时可以传入若干个int类型的元素
        //ints是用来可变参数的
        //可变参数传入的值被封装到一个数组中了,这个数组的名字就是参数名
        int sum = 0;
        for(int i : ints){
            sum += i;
        }
        return sum;
    }
    
//    public static int sum(int a, int b, int c, int d) {
//        return a + b + c + d;
//    }
//
//    public static int sum(int a, int b, int c) {
//        return a + b + c;
//    }
//
//    public static int sum(int a, int b) {
//        return a + b;
//    }
}

九、静态导入

静态导入:前提使用的方法是静态的

package day14;
/*
  静态导入: 前提使用的方法是静态的
    */
public class StaticImportDemo1 {
    public static void main(String[] args) {
//        System.out.println(Math.max(10,45));
//        System.out.println(Math.max(312,45));
//        System.out.println(Math.max(2,24));
//        System.out.println(Math.max(13,512));

        System.out.println(max(213,634));
        System.out.println(java.lang.Math.max(213,3));
        System.out.println(Math.max(213,52));
//        System.out.println(max(81,234));
//
//        System.out.println(min(232,51));
    }
    
    //使用的是自己的
    public static int max(int a,int b){
        System.out.println("这是我们自己写的。。。。。。");
        System.out.println("a是b的第一个参数");
        return 0;
    }
}

十、Set接口概述

特点:元素唯一且无序

1、HashSet类

使用Set集合存储自定义对象,当对象的姓名和年龄都一样的时候,将这两个对象认为是重复了,进行去重

HashSet:底层数据结构是哈希表

案例:

Student类:

package day14;
import java.util.Objects;

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

    public Student1() {
    }

    public Student1(String name, int age) {
        this.name = name;
        this.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;
    }

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

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

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

SetDemo2类

package day14;

import day14.Student1;

import java.util.HashSet;

public class SetDemo2 {
    public static void main(String[] args) {
        //创建一个Set集合对象
        HashSet<Student1> set1 = new HashSet<>();

        //创建元素对象
        Student1 s1 = new Student1("张三", 18);
        Student1 s2 = new Student1("李四", 18);
        Student1 s3 = new Student1("王五", 16);
        Student1 s4 = new Student1("张三", 18);
        Student1 s5 = new Student1("赵六", 15);

        //向集合中添加元素
        set1.add(s1);
        set1.add(s2);
        set1.add(s3);
        set1.add(s4);
        set1.add(s5);

        //遍历集合
        for(Student1 student1: set1){
            System.out.println(student1);
        }
    }
}

  LinkedHashSet(底层数据结构是哈希表和双链表)

package day14;

import java.util.LinkedHashSet;

/*
    LinkedHashSet是继承自HashSet类, 底层数据结构是哈希表和双链表,哈希表保证了元素的唯一性,双链表保证了元素的有序

        Collection: 接口
         - List(元素有序且可以发生重复,且有索引的概念)
            - ArrayList(底层数据结构是数组,查询快,增删慢,线程不安全,效率高)
            - Vector(底层数据结构是数组,查询快,增删慢,线程安全的,效率低,即便是安全的,我们以后也不使用)
            - LinkedList(底层数据结构是双链表,增删快,查询慢,线程不安全,效率高)
         - Set(元素唯一且无序,没有索引)
            - HashSet(底层数据结构是哈希表)
                - LinkedHashSet(底层数据结构是哈希表和双链表)
 */
public class LinkedHashSetDemo1 {
    public static void main(String[] args) {
        LinkedHashSet<String> set1 = new LinkedHashSet<>();

        set1.add("hello");
        set1.add("world");
        set1.add("hello");
        set1.add("java");
        set1.add("hello");
        set1.add("hadoop");
        set1.add("spark");
        set1.add("hello");

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

 为什么HashSet中add方法会产生去重,且输出是无序的

HashSet中add方法源码解释

// 结论1: HashSet中的add方法底层实际上调用的是HashMap中的put方法
// 结论2: 观察HashMap中put方法源码后发现,底层调用了元素类中的hashCode()方法
// 结论3: 底层判断元素是否已经存在的方式是,判断待添加元素的hashCode()方法和equals()方法的结果是否与已经存在集合中元素的hashCode()方法和equals()方法的结果一样
//      若一样,就进行去重,若不一样,就将待插入的元素添加到集合中
// 我们自己定义的Student类中并没有写hashCode()方法和equals()方法,所以底层调用都是该类的父类Object中的hashCode()方法和equals()方法,比较的都是地址值
// 而每一个元素对象都是单独new出来的,所以比较的结果永远是比较地址值,永远是false
// 我们要想比较内容的话,应该在元素类中重写父类Object类中的hashCode()方法和equals()方法, 自动生成即可


/*
    Student s1 = new Student("张三", 18);
    set1.add(s1);

*/
class HashSet{
    private transient HashMap<E,Object> map;
    private static final Object PRESENT = new Object();

    public HashSet() {
        map = new HashMap<>();
    }

    public boolean add(E e) {
        // E - Student
        // e - s1
        return map.put(e, PRESENT)==null;
    }
}


class HashMap{
    public V put(K key, V value) {
        // key - s1
        // value - new Object()
        return putVal(hash(key), key, value, false, true);
    }

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        Node<K,V>[] tab; // null
        Node<K,V> p;  // null
        int n; // 0
        int i; // 0

        //初始化hash table
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;

        //将第一个元素当作哈希表的第一个节点
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);

        // 从第二个元素做添加的时候,走这里
        else {
            Node<K,V> e;
            K k; // null
            if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            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;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
}

2、TreeSet类

TreeSet(底层数据结构是红黑树,自己指定排序方式)

两种排序方式:

        1.自然排序

        2.比较器排序

思考:使用TreeSet存储自定义学生对象,按照年龄从大到小排序,且去重

基本用法:

package day14;
import java.util.TreeSet;

public class TreeSetDemo1 {
    public static void main(String[] args) {
        TreeSet<String> set1 = new TreeSet<>();

        set1.add("hello");
        set1.add("world");
        set1.add("hello");
        set1.add("java");
        set1.add("hello");
        set1.add("hadoop");
        set1.add("spark");
        set1.add("hello");
        set1.add("apple");

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

练习:使用TreeSet存储自定义学生对象,按照年龄从小到大排序,且去重

自定义Student类

package day14;

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

    public Student2() {
    }

    public Student2(String name, int age) {
        this.name = name;
        this.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;
    }

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

    @Override
    public int compareTo(Student2 o){
        int i = this.age - o.age;
        return(i==0)?this.name.compareTo(o.name):i;
    }

}

测试类TreeSetDemo2类

package day14;

import java.util.TreeSet;

/*
    使用TreeSet存储自定义学生对象,按照年龄从小到大排序,且去重

    若创建TreeSet对象是无参构造方法的话,底层创建TreeMap无参构造方法创建的,comparator = null;走的自然排序

 */
public class TreeSetDemo2 {
    public static void main(String[] args) {
        //创建TreeSet的集合对象
        TreeSet<Student2> set1 = new TreeSet<>();

        //创建元素对象
        Student2 s1 = new Student2("张三", 18);
        Student2 s2 = new Student2("李四", 18);
        Student2 s3 = new Student2("王五", 16);
        Student2 s4 = new Student2("张三", 18);
        Student2 s5 = new Student2("赵六", 15);

        //添加元素
        set1.add(s1);
        set1.add(s2);
        set1.add(s3);
        set1.add(s4);
        set1.add(s5);

        //遍历集合
        for (Student2 student2 : set1) {
            System.out.println(student2);
        }

    }
}

TreeSet的比较器排序

通过观察源码发现想要使用比较器排序,就要保证TreeMap中的comparator参数不是null,要想保证TreeMap中的comparator参数不是null,就得使用TreeMap有参构造方法来创建,就要保证在创建TreeSet对象的时候,传入一个实现了Comparator的对象

package day14;

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

/*
    TreeSet的比较器排序
    通过观察源码发现.要想使用比较器排序,就得保证TreeMap中的comparator参数不是null,
    要想保证TreeMap中的comparator参数不是null,就得使用TreeMap有参构造方法来创建,就要保证在创建TreeSet对象的时候
    ,传入一个实现了Comparator的对象
 */

//class ComparatorImpl implements Comparator<Student3>{
//    @Override
//    public int compare(Student3 o1, Student3 o2) {
//        //cpr.compare(key, t.key);
//        // o1 - key - 待插入的元素
//        // o2 - t.key - 根的元素
//        //需求:按照年龄从小到大排序,并去重
//        int i = o2.getAge() - o1.getAge();
//        return (i==0)?o1.getName().compareTo(o2.getName()):i;
//    }
//}

public class TreeSetDemo3 {
    public static void main(String[] args) {
//        TreeSet<Student3> set1 = new TreeSet<>(new ComparatorImpl());

        TreeSet<Student3> set1 = new TreeSet<>(new Comparator<Student3>() {
            @Override
            public int compare(Student3 o1, Student3 o2) {
                //cpr.compare(key, t.key);
                // o1 - key - 待插入的元素
                // o2 - t.key - 根的元素
                //需求:按照年龄从小到大排序,并去重
                int i = o2.getAge() - o1.getAge();
                return (i == 0) ? o1.getName().compareTo(o2.getName()) : i;
            }
        });

        //创建元素对象
        Student3 s1 = new Student3("张三", 18);
        Student3 s2 = new Student3("李四", 18);
        Student3 s3 = new Student3("王五", 16);
        Student3 s4 = new Student3("张三", 18);
        Student3 s5 = new Student3("赵六", 15);

        //添加元素
        set1.add(s1);
        set1.add(s2);
        set1.add(s3);
        set1.add(s4);
        set1.add(s5);

        //遍历集合
        for (Student3 student : set1) {
            System.out.println(student);
        }
    }
}

studen类:

package com.shujia.day14;

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

    public Student3() {
    }

    public Student3(String name, int age) {
        this.name = name;
        this.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;
    }

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

TreeSet中的add方法源码解释

// 结论1: TreeSet调用的add方法底层是调用了TreeMap中的put方法进行添加元素的


/*
    //创建一个TreeSet对象
    TreeSet<String> set1 = new TreeSet<>();
*/
class TreeSet{
    private transient NavigableMap<E,Object> m; // null
    private static final Object PRESENT = new Object();

    public TreeSet() {
        this(new TreeMap<E,Object>()); // this(...)
    }

    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }

    //set1.add("hello");
    //set1.add("world");
    public boolean add(E e) {
        // E - String
        // e - "world"
        // PRESENT - new Object();
        return m.put(e, PRESENT)==null;
    }
}

class TreeMap{
    private transient Entry<K,V> root; // null

    public TreeMap() {
        comparator = null;
    }

    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }


    public V put(K key, V value) {
        // key - "world"
        // value - new Object()
        Entry<K,V> t = root; // 第一个元素添加的时候,树连根都没有,是null

        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;

        Entry<K,V> parent;

        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator; // null


        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key; // Student2
            do {
                parent = t; // "hello"
                cmp = k.compareTo(t.key); // "world".compareTo("hello")
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }
}

十一、Collections工具类

静态成员方法:

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 day15;

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

public class CollectionsDemo {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("hello");
        list1.add("world");
        list1.add("hadoop");
        list1.add("apple");

        System.out.println("list1: "+list1);
        System.out.println("====================");

        Collections.sort(list1);//对集合进行升序排序
        System.out.println("list1: "+list1);
        //list1: [apple, hadoop, hello, world]

        //public static <T> int binarySearch(List<?> list,T key) 在针对List集合中二分查找某个元素,返回该元素的下标索引
        System.out.println(Collections.binarySearch(list1,"hello"));

        //public static <T> T max(Collection<?> coll)
        System.out.println(Collections.max(list1));

        //public static void reverse(List<?> list) 将集合元素反转
        Collections.reverse(list1);
        System.out.println("list1: "+list1);

        //public static void shuffle(List<?> list) 将List集合元素进行随机打乱,每次运行结果都不一样
        Collections.shuffle(list1);
        System.out.println("list1: "+list1);

        //即便Vector是线程安全的,我们今后也不用
        //原因是我们可以通过Collections工具类对ArrayList或其他不安全的集合做操作,变成安全的。
        List<String> list2 = Collections.synchronizedList(list1);
        //后续用list2,跟不安全的用法一毛一样,没有任何区别,只是后续这个List集合是安全的了。

    }
}

十二、Map接口

Map:存储元素的特点是每一个元素是一个键对值{【key:12】,【value:10000】}

Map集合的共同拥有的特点:

  • Map集合中的元素,键是唯一的,不会在一个Map集合发现两个相同的键
  • Map集合中,值是可以发生重复的
  • Map集合的唯一性,排序都是针对键来说的,值是跟着键走的

Map接口中的成员方法:

V put(K key,V value)
V remove(Object key)
void clear()
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
int size()

package day15;

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

public class MapDemo1 {
    public static void main(String[] args) {
        //创建一个Map对象
        Map<Integer,String> map1 = new HashMap<>();

        //V put(K key,V value) 向集合中添加键值对元素  返回的是被覆盖的键对应的那个值
        System.out.println(map1.put(1001, "张三"));
        System.out.println(map1.put(1002, "李四"));
        System.out.println(map1.put(1003, "王五"));
        System.out.println(map1.put(1001, "赵六")); // 会将上面1001键的值进行覆盖操作
        System.out.println(map1.put(1004, "孙七"));

        System.out.println("map1: "+map1);
        System.out.println("----------------------------------");

        //V remove(Object key) 根据键删除一个键值对元素 返回被删除键值对的值
//        System.out.println(map1.remove(1001));
//        System.out.println("map1: "+map1);
//        System.out.println("----------------------------------");

        //void clear()
//        map1.clear();
//        System.out.println("map1: "+map1);
//        System.out.println("----------------------------------");

        //boolean containsKey(Object key) 判断键是否存在
        System.out.println(map1.containsKey(1001));
        System.out.println("----------------------------------");

        //boolean containsValue(Object value) 判断值是否存在
        System.out.println(map1.containsValue("孙七"));
        System.out.println("----------------------------------");

        //boolean isEmpty()
        System.out.println(map1.isEmpty());
        System.out.println("----------------------------------");

        //int size() 获取集合中的键值对的个数
        System.out.println(map1.size());
    }
}

Map集合的遍历

遍历方式:

        方式1:先一次性获取所有的键,遍历键根据键找到值

        方式2:可以拿到每一键对值组成的一个对象,遍历这个对象中的元素得到每一个键值对中 的键值和。

package day15;


import javax.swing.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
    map集合的遍历
    遍历方式:
        方式1:先一次性获取所有的键,遍历键根据键找到值。
        方式2:可以拿到每一键值对组成的一个对象,遍历这个对象中的元素得到每一个键值对中的键和值。

 */
public class MapDemo2 {
    public static void main(String[] args) {
        //创建一个Map对象
        Map<Integer,String> map1 = new HashMap<>();

        //V put(K key,V value)向集合中添加键对值元素,返回的是被覆盖的键对应的那个值
        System.out.println(map1.put(1001, "张三"));
        System.out.println(map1.put(1004, "李四"));
        System.out.println(map1.put(1003, "王五"));
        System.out.println(map1.put(1001, "赵六")); // 会将上面1001键的值进行覆盖操作
        System.out.println(map1.put(1002, "孙七"));

        System.out.println("map1: "+map1);
        System.out.println("===================================");

        //方式一:先一次性获取所有的键,遍历键根据键找到值
        //keySet()获取map集合所有的键,返回所有的键组成的一个Set集合
        Set<Integer> keys = map1.keySet();
        for(Integer key: keys){
            String value = map1.get(key);
            System.out.println(key + "-" + value);
        }
        System.out.println("---------------------------------");

        //方式二:可以拿到每一个键值组成的一个对象,遍历这个对象中的元素得到每一个键值对中的键和值
        //entrySet() 获取每一个键值对,组成一个Set集合
        Set<Map.Entry<Integer,String>> entries = map1.entrySet();
        for (Map.Entry<Integer,String>entry : entries){
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"-"+value);
        }
    }
}

十三、HashMap类(Map接口)

HashMap <Student2,String>

这里的话,我们认为当学生的姓名和年龄一样的时候,认为是重复的

如果有一个自定义类型当作键的类型的时候,想要保证唯一性,就需要元素重写hashCode()和equals()方法

自定义student类:

package day15;

import java.util.Objects;

public class Student implements Comparable<Student>{

    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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;
    }

    @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 int compareTo(Student o) {
        int i = this.age - o.age;
        return (i==0)?this.name.compareTo(o.name):i;
    }
}

测试HashMapDemo1类:

package day15;

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

public class HashMapDemo1 {
    public static void main(String[] args) {
        HashMap<Student,String> map1 = new HashMap<>();

        map1.put(new Student("张三",18),"跳舞");
        map1.put(new Student("李四",17),"美女");
        map1.put(new Student("王五",18),"篮球");
        map1.put(new Student("赵六",19),"rap");
        map1.put(new Student("孙七",17),"美女");

        Set<Student> student2s = map1.keySet();
        for (Student student2 : student2s) {
            System.out.println(student2);
        }
    }
}

面试题:HashMap和Hashtable的区别

区别1:HashMap中的键和值都允许为null值,Hashtable的键和值都不允许null

区别2:HashMap是线程不安全的,Hashtable是线程安全的,因为它的方法基本都有synchronized
 

package day15;

import java.util.HashMap;
import java.util.Hashtable;

/*
    面试题:HashMap和Hashtable的区别
    区别1:HashMap中的键和值都允许为null值,Hashtable的键和值都不允许null
    区别2:HashMap是线程不安全的,Hashtable是线程安全的,因为它的方法基本都有synchronized
 */
public class HashMapDemo2 {
    public static void main(String[] args) {
        HashMap<String, String> map1 = new HashMap<>();
//        map1.put(null,"qwe");
//        map1.put(null,null);
//        map1.put("qwerwqr",null);

        Hashtable<String, String> map2 = new Hashtable<>();
//        map2.put(null,"qwe");
//        System.out.println(map2);
//        map2.put("zxc",null);
    }
}

十四、LinkedHashMap类(Map接口)

格式:

public class LinkedHashMap extends HashMap{}

底层数据结构是哈希表和链表 

package day15;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Set;
/*
    class LinkedHashMap extends HashMap{}
    底层数据结构是哈希表和链表
 */

public class LinkedHashMapDemo1 {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map1 = new LinkedHashMap<>();
//        HashMap<Integer, String> map1 = new HashMap<>();
        map1.put(1001, "张三");
        map1.put(1008, "李四");
        map1.put(1006, "王五");
        map1.put(1001, "赵六");
        map1.put(1004, "孙七");
        System.out.println("map1: "+map1);

    }
}

十五、TreeMap类

package day15;

import java.util.Set;
import java.util.TreeMap;

public class TreeMapDemo1 {
    public static void main(String[] args) {
        TreeMap<Student2, String> map1 = new TreeMap<>();
        map1.put(new Student2("a1", 15), "唱歌");
        map1.put(new Student2("a5", 19), "跳舞");
        map1.put(new Student2("a1", 15), "rap");
        map1.put(new Student2("a2", 12), "打篮球");
        map1.put(new Student2("a4", 17), "打游戏");

        Set<Student2> student2s = map1.keySet();
        for (Student2 student2 : student2s) {
            String value = map1.get(student2);
            System.out.println(student2 + "-" + value);
        }
    }
}

十六、练习

-- 1、"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)


-- 2、ArrayList嵌套HashMap


-- 3、键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台


-- 4、获取10个1-20之间的随机数,要求不能重复


-- 5、使用List和Map存放多个图书信息,遍历并输出。其中商品属性:编号,名称,单价,出版社;使用商品编号作为Map中的key。


-- 6、使用HashSet和TreeSet存储多个商品信息,遍历并输出;其中商品属性:编号,名 称,单价,出版社;要求向其中添加多个相同的商品,验证集合中元素的唯一性。
提示:
向HashSet中添加自定义类的对象信息,需要重写hashCode和equals( )
向TreeSet中添加自定义类的对象信息,需要实现Comparable接口,指定比较规则


-- 7、实现List和Map数据的转换。具体要求如下:
功能1:定义方法public void listToMap( ){ }将List中Student元素封装到Map中
功能2:定义方法public void mapToList( ){ }将Map中Student映射信息封装到List


-- 8、 假如有以下email数据“aa@sohu.com,bb@163.com,cc@sina.com,.. ”现需要把email 中的用户部分和邮件地址部分分离,分离后以键值对应的方式放入HashMap?


-- 9、由控制台按照固定格式输入学生信息,包括学号,姓名,年龄信息,当输入的内容 为exit退出;将输入的学生信息分别封装到一个Student对象中,再将每个Student  对象加入到一个集合中,要求集合中的元素按照年龄大小正序排序;

十七、答案

-- 1、"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)

package day15.HomeWork6;

import sun.reflect.generics.tree.Tree;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class HomeWorkTest6 {
    public static void main(String[] args) {
        String s = "aababcabcdabcde";
        TreeMap<Character,Integer>map1 = new TreeMap<>();

        char[] chars = s.toCharArray();

        for(char c:chars){
            //将字符作为键存储在Map集合中
            //先判断集合中是否有该建、若没有,就赋值该字符为键,1为值存储【c,1】
            //若集合已经存在该键了,在原来键对应的值基础之上加一【c,1】->【c,2】
            if(!map1.containsKey(c)){
                map1.put(c,1);
            }else{
                map1.put(c,map1.get(c)+1);
            }
        }


        StringBuilder stringBuilder = new StringBuilder();
        Set<Map.Entry<Character,Integer>> entries = map1.entrySet();

        for(Map.Entry<Character,Integer>entry:entries){
            Character key = entry.getKey();
            Integer value = entry.getValue();
            stringBuilder.append(key).append("(").append(value).append(")");
        }
        String Set = stringBuilder.toString();
        System.out.println(Set);
    }
}

-- 2、ArrayList嵌套HashMap

package day15.HomeWork7;

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

public class HomeWorkTest7 {
    public static void main(String[] args) {

        ArrayList<HashMap<Integer,String>> list = new ArrayList<>();


        HashMap<Integer,String> map1 = new HashMap<>();
        map1.put(1001,"小张");
        map1.put(1002,"小李");
        map1.put(1003,"小王");

        HashMap<Integer,String> map2 = new HashMap<>();
        map2.put(1004,"小张1");
        map2.put(1005,"小李1");
        map2.put(1006,"小王1");

        HashMap<Integer,String> map3 = new HashMap<>();
        map3.put(1007,"小张2");
        map3.put(1008,"小李2");
        map3.put(1009,"小王2");

        list.add(map1);
        list.add(map2);
        list.add(map3);

        for(HashMap<Integer, String> map:list){
            System.out.println("====================================");
            Set<Map.Entry<Integer,String>> entries = map.entrySet();
            for(Map.Entry<Integer,String>entry:entries){
                Integer key = entry.getKey();
                String value = entry.getValue();
                System.out.println(key+"|"+value);
            }
        }
    }
}

-- 3、键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台

Student类:

package day15.HomeWork8;

public class Student {
    private String name;
    private int chinese;
    private int math;
    private int english;

    public Student() {
    }

    public Student(String name, int chinese, int math, int english) {
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    public String getName() {
        return name;
    }

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

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getEnglish() {
        return english;
    }

    public void setEnglish(int english) {
        this.english = english;
    }

    public int getSum(){
        return chinese + math + english;
    }

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

测试类:

package day15.HomeWork8;

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

public class HomeWorkTest8 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        TreeSet<Student>set = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //显示条件:
                int i = o2.getSum()- o1.getSum();
                //隐式条件:
                //总分一样,各科的分数不一定一样
                //总分一样,语文成绩不一定一样
                int i2 = (i==0)? o2.getChinese() - o1.getChinese():i;
                //总分,语文成绩一样,数学成绩不一定一样
                int i3 = (i2==0)? o2.getMath() - o1.getMath():i2;
                //各科分数一样,姓名不一定一样
                return (i3==0)? o2.getName().compareTo(o1.getName()):i3;
            }
        });

        Student student;

        for (int i = 1; i <= 5; i++) {
            System.out.println("请输入第 "+i+" 个学生的信息:");
            System.out.print("姓名:");
            String name = sc.next();
            System.out.print("语文成绩:");
            int chinese = sc.nextInt();
            System.out.print("数学成绩:");
            int math = sc.nextInt();
            System.out.print("英语成绩:");
            int english = sc.nextInt();

            //创建一个学生对象,将当前学生的信息进行封装
            student = new Student(name,chinese,math,english);

            //将学生对象添加到集合中
            set.add(student);
            System.out.println("----------------------------------------------------------");
        }
        for (Student student1 : set) {
            System.out.println(student1.getName()+"\t\t"+student1.getChinese()+"\t\t"+student1.getMath()+"\t\t"+student1.getEnglish()+"\t\t"+student1.getSum());
        }
    }
}

-- 4、 获取10个1-20之间的随机数,要求不能重复

/*
分析:
    1.创建一个空的List集合
    2、因为生成随机数是可能发生重复的,所以生成随机数的次数是不确定的,采用while循环
    3、每次生成一个数字,判断集合是否存在,若不存在,就添加到集合中,次数加一,反之继续循环
    4、直到次数为10的时候,跳出循环,生成完毕。
*/

package day14.HomeWork;

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

public class HomeWork01 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Random r = new Random();
        int count=0;
        int num=0;

        while(count<10){
            int number = r.nextInt(20)+1;
            if(!list.contains(number)){
                list.add(number);
                count++;
            }
            num++;
        }
        System.out.println(list +"|"+num);
    }
}

-- 5、使用List和Map存放多个图书信息,遍历并输出。其中商品属性:编号,名称,单价,出版社;使用商品编号作为Map中的key。

Goods类:

package day15.HomeWork1;

public class Goods {
    private String Id;
    private String name;
    private double price;
    private String publisher;

    public Goods() {
    }

    public Goods(String id, String name, double price, String publisher) {
        Id = id;
        this.name = name;
        this.price = price;
        this.publisher = publisher;
    }

    public String getId() {
        return Id;
    }

    public void setId(String id) {
        Id = id;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "Id='" + Id + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", publisher='" + publisher + '\'' +
                '}';
    }
}

测试类:

package day15.HomeWork1;
import java.util.*;

public class HomeWorkTest1 {
    public static void main(String[] args) {

        Goods book1 = new Goods("1001","红岩",12.0,"人民出版社");
        Goods book2 = new Goods("1002","苦难辉煌",18.5,"商务出版社");
        Goods book3 = new Goods("1003","浮士德",55.0,"译林出版社");

        //第一种要求,使用List存放图书信息
        List<Goods> commodity1 = new ArrayList<>();
        commodity1.add(book1);
        commodity1.add(book2);
        commodity1.add(book3);

        for(Goods books:commodity1){
            System.out.println(books);
        }
        System.out.println("----------------------------------------------------");

        //第二种要求,使用Map存放图书信息
        Map<String,Goods> commodity2 = new HashMap<>();

        commodity2.put(book1.getId(), book1);
        commodity2.put(book2.getId(), book2);
        commodity2.put(book3.getId(), book3);

        Set<Map.Entry<String,Goods>> books = commodity2.entrySet();
        for (Map.Entry<String,Goods> book:books){
            String key = book.getKey();
            Goods value = book.getValue();
            System.out.println(value);
        }
    }
}

-- 6、使用HashSet和TreeSet存储多个商品信息,遍历并输出;其中商品属性:编号,名称,单价,出版社;要求向其中添加多个相同的商品,验证集合中元素的唯一性。

commodity类:

package day15.HomeWork2;

import java.util.Objects;

public class commodity implements Comparable<commodity> {

    private int ID;
    private String name;
    private double price;
    private String publisher;

    public commodity() {
    }

    public commodity(int ID, String name, double price, String publisher) {
        this.ID = ID;
        this.name = name;
        this.price = price;
        this.publisher = publisher;
    }

    public int getID() {
        return ID;
    }

    public void setID(int ID) {
        this.ID = ID;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    @Override
    public String toString() {
        return "commodity{" +
                "ID='" + ID + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", publisher='" + publisher + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        commodity commodity = (commodity) o;
        return price == commodity.price && Objects.equals(ID, commodity.ID) && Objects.equals(name, commodity.name) && Objects.equals(publisher, commodity.publisher);
    }

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

    @Override
    public int compareTo(commodity o) {
        return this.ID-o.ID;
    }
}

测试类:

package day15.HomeWork2;

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class HomeWorkTest2 {
    public static void main(String[] args) {

        //创建对象元素
       commodity book1 = new commodity(1001,"红岩",12.0,"人民出版社");
       commodity book2 = new commodity(1002,"苦难辉煌",18.5,"商务出版社");
       commodity book3 = new commodity(1003,"浮士德",55.0,"译林出版社");

        //创建集合对象,按照要求一,使用HashSet存储数据
        Set<commodity> information1 = new HashSet<>();

        //添加元素对象
        information1.add(book1);
        information1.add(book2);
        information1.add(book3);

        for(commodity book: information1){
            System.out.println(book);
        }

        System.out.println("======================================");
        //按照需求而使用TreeHash排序,使用自然排序
        Set<commodity> information2 = new TreeSet<>();

        information2.add(book1);
        information2.add(book2);
        information2.add(book3);

        for(commodity book: information2){
            System.out.println(book);
        }
    }
}

-- 7、实现List和Map数据的转换。具体要求如下:
功能1:定义方法public void listToMap( ){ }将List中Student元素封装到Map中
功能2:定义方法public void mapToList( ){ }将Map中Student映射信息封装到List

Student类:

package day15.HomeWork3;

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

    public Student() {
    }

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

    public int getId() {
        return Id;
    }

    public void setId(int id) {
        Id = id;
    }

    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 String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

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

测试类:

package day15.HomeWork3;

import java.util.*;

public class HomeWorkTest3 {

    public void listToMap(){
        List<Student> students = new ArrayList<>();

        //创建元素对象
        Student student1 = new Student(1001,"小张",18,"男");
        Student student2 = new Student(1002,"小李",17,"男");
        Student student3 = new Student(1003,"小王",14,"男");
        Student student4 = new Student(1004,"小赵",19,"女");
        Student student5 = new Student(1005,"小孙",18,"女");

        students.add(student1);
        students.add(student2);
        students.add(student3);
        students.add(student4);
        students.add(student5);

        for(Student student:students){
            System.out.println(student);
        }

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

        Map<Integer,Student> map1 = new HashMap<>();
        for(Student student:students){
            map1.put(student.getId(),student);
        }

        Set<Map.Entry<Integer,Student>> entries = map1.entrySet();
        for(Map.Entry<Integer,Student> entry: entries){
            System.out.println(entry.getValue());
        }
    }

    public void mapToList(){
        Map<Integer,Student>map = new HashMap<>();

        //创建元素对象
        Student student1 = new Student(1001,"小张1",18,"男");
        Student student2 = new Student(1002,"小李1",17,"男");
        Student student3 = new Student(1003,"小王1",14,"男");
        Student student4 = new Student(1004,"小赵1",19,"女");
        Student student5 = new Student(1005,"小孙1",18,"女");

        map.put(student1.getId(), student1);
        map.put(student2.getId(), student2);
        map.put(student3.getId(), student3);
        map.put(student4.getId(), student4);
        map.put(student5.getId(), student5);

        List <Student>students = new ArrayList<>();
        Set<Map.Entry<Integer,Student>> entries = map.entrySet();
        for(Map.Entry<Integer,Student> entry:entries){
            students.add(entry.getValue());
        }
        for(Student stu:students){
            System.out.println(stu);
        }
    }

    public static void main(String[] args) {
        HomeWorkTest3 hw3 = new HomeWorkTest3();
        hw3.listToMap();
        System.out.println("-----------------------------------------------");
        hw3.mapToList();

    }
}

-- 8、假如有以下email数据“aa@sohu.com,bb@163.com,cc@sina.com,.. ”现需要把email 中的用户部分和邮件地址部分分离,分离后以键值对应的方式放入HashMap?

package day15.HomeWork4;

import com.sun.crypto.provider.HmacPKCS12PBESHA1;

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

public class HomeWorkTest4 {
    public static void main(String[] args) {
        String email = "aa@sohu.com,bb@163.com,cc@sina.com";
        String[] email1 = email.split(",");
        Map<String,String> map = new HashMap<>();
        for (String s : email1) {
            String[] tmp = s.split("@");
            map.put(tmp[0], tmp[1]);
        }

        Set<Map.Entry<String,String>> entries = map.entrySet();
        for(Map.Entry<String,String>entry:entries){
            System.out.println(entry.getKey()+"--"+entry.getValue());
        }
    }
}

-- 9、由控制台按照固定格式输入学生信息,包括学号,姓名,年龄信息,当输入的内容 为exit退出;将输入的学生信息分别封装到一个Student对象中,再将每个Student  对象加入到一个集合中,要求集合中的元素按照年龄大小正序排序

Student类:

package day15.HomeWork5;

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

    public Student() {
    }

    public Student(Integer id, String name, Integer age) {
        Id = id;
        this.name = name;
        this.age = age;
    }

    public Integer getId() {
        return Id;
    }

    public void setId(Integer id) {
        Id = id;
    }

    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 "Student{" +
                "Id=" + Id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
}

测试类:

package day15.HomeWork5;

import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class HomeWorkTest5 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Set<Student> students = new TreeSet<>();
        while(true){
            System.out.println("输入(格式:编号#姓名#年龄):");
            String stu = sc.nextLine();
            if(stu.equals("exit")){
                break;
            }else{
                String[] stu1 = stu.split("#");
                Student student = new Student(Integer.parseInt(stu1[0]),stu1[1],Integer.parseInt(stu1[2]));
                students .add(student);
            }
        }
        for(Student stu:students){
            System.out.println(stu);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值