Java进阶学习3:【List接口、数据结构、Set接口、Collections工具类】

  • A+
所属分类:Java Java进阶

01. List接口的特点

/*
    List接口是Collection下面的一个子接口。

    List接口有三个特点:
        1. 有序。(有序不是按顺序排序, 有序指的是怎么存,就怎么取)
        2. 有索引。 (可以根据索引获取元素)
        3. 可重复 (可以存放重复的元素)

    List是接口,如果要用,需要使用实现类,最常用的实现类是ArrayList
 */
public class Demo01List {
    public static void main(String[] args) {
        //定义一个集合
        List<String> list = new ArrayList<>();
        //添加元素
        list.add("貂蝉");
        list.add("西施");
        list.add("王昭君");
        //输出集合
        //1. 有序。
        System.out.println("list:" + list);
        //2. 有索引。 (可以根据索引获取元素)
        System.out.println(list.get(1));
        //3. 可重复 (可以存放重复的元素)
        list.add("西施");
        list.add("西施");
        list.add("西施");
        list.add("西施");
        list.add("西施");
        list.add("西施");
        list.add("西施");
        list.add("西施");
        System.out.println("list:" + list);
    }
}

02. List接口中的常见方法

/*
    List接口中常见的方法
        public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
        (常用)public E get(int index) :返回集合中指定位置的元素。
        public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
        public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
 */
public class Demo02ListMethod {
    public static void main(String[] args) {
        method3();
    }

    /*
         public E set(int index, E element): 使用参数element替换掉集合index位置上的元素。返回的是被替换掉的元素
     */
    public static void method3() {
        //定义集合
        List<String> list = new ArrayList<>();
        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        //输出集合
        System.out.println("list:" + list);
        //把集合中的java替换为php
        String str = list.set(2, "php");
        System.out.println("list:" + list);
        System.out.println("str:" + str);
    }

    /*
        public E remove(int index) : 移除列表中指定位置的元素, 返回的是被删除的元素。
     */
    public static void method2() {
        //定义集合
        List<String> list = new ArrayList<>();
        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        //输出
        System.out.println("删除前:" + list);
        //删除索引为1的元素
        String str = list.remove(1);
        System.out.println("删除后:" + list); //[hello, java]
        System.out.println("str:" + str); //world
    }

    /*
        public void add(int index, E element): 在指定索引位置添加元素。
        (常用)public E get(int index) :返回集合中指定位置的元素。
     */
    public static void method() {
        //定义集合
        List<String> list = new ArrayList<>();
        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        //输出集合
        System.out.println("list:" + list); //[hello, world, java]
        //向集合中索引为1的位置插入一个元素,插入 "詹姆斯高斯林"
        list.add(1, "詹姆斯高斯林");
        System.out.println("list:" + list); //[hello, 詹姆斯高斯林, world, java]
        //使用get,获取索引为0的元素
        System.out.println("索引为0的元素是:" + list.get(0));
    }
}

03. 栈结构的特点

先进后出,参考 Java基础学习12:【List、Set、数据结构、Collections】中的图片。

04. 队列结构的特点

先进先出,参考 Java基础学习12:【List、Set、数据结构、Collections】中的图片。

05. 数组结构的特点

查询快,增删慢, 参考 Java基础学习12:【List、Set、数据结构、Collections】中的图片。

06. 链表结构的特点

查询慢,增删快,参考 Java基础学习12:【List、Set、数据结构、Collections】中的图片。

07. 红黑树

参考 Java基础学习12:【List、Set、数据结构、Collections】中的图片。

08. ArrayList的特点

ArrayList 是在采用数组保存数据。
特点: 查询快, 增删慢
ArrayList是我们以后用的最多的集合。

09. LinkedList的特点

LinkedList也是List接口下面的一个实现类。

LinkedList内部是在使用链表(双向链表)保存数据

特点: 查询慢,增删快

10. LinkedList独有的方法

/*
    常见方法(LinkedList特有的方法):
        public void addFirst(E e) :将指定元素插入此列表的开头。
        public void addLast(E e) :将指定元素添加到此列表的结尾。
        public E getFirst() :返回此列表的第一个元素。
        public E getLast() :返回此列表的最后一个元素。
        public E removeFirst() :移除并返回此列表的第一个元素。
        public E removeLast() :移除并返回此列表的最后一个元素。
        public E pop() :从此列表所表示的堆栈处弹出一个元素。
        public void push(E e) :将元素推入此列表所表示的堆栈。
 */
public class Demo04LinkedList {
    public static void main(String[] args) {
        method4();
    }
    /*
        public E pop(): 弹出。 删除集合中的第一个元素并将该元素返回。
        public void push(E e): 压入。 向集合的第一个位置添加元素
     */
    public static void method4() {
        //定义集合
        LinkedList<String> list = new LinkedList<>();
        //调用add方法添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        System.out.println("操作前list:" + list); //[hello, world, java]
        // public E pop(): 弹出。 删除集合中的第一个元素并将该元素返回。
        //String str = list.pop();
        //System.out.println("操作后list:" + list); //[world, java]
        //System.out.println("str:" + str); //hello

        //public void push(E e): 压入。 向集合的第一个位置添加元素
        list.push("php");
        System.out.println("操作后list:" + list); //[php, hello, world, java]
    }

    /*
        public E removeFirst() :删除集合中的第一个元素, 返回被删除的元素
        public E removeLast() :删除集合中的最后一个元素, 返回被删除的元素
     */
    public static void method3() {
        //定义集合
        LinkedList<String> list = new LinkedList<>();
        //调用add方法添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        System.out.println("删除前:" + list); //[hello, world, java]
        //public E removeFirst() :删除集合中的第一个元素
        //String str = list.removeFirst();
        //System.out.println("删除后:" + list); //[world, java]
        //System.out.println("str:" + str); //hello

        //public E removeLast() :删除集合中的最后一个元素
        String str = list.removeLast();
        System.out.println("删除后:" + list); //[hello, world]
        System.out.println("str:" + str); //java
    }

    /*
         public E getFirst() :获取集合中的第一个元素
         public E getLast() :获取集合中的最后一个元素
     */
    public static void method2() {
        //定义集合
        LinkedList<String> list = new LinkedList<>();
        //调用add方法添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        System.out.println("获取首个元素:" + list.getFirst()); //hello
        System.out.println("获取尾部元素:" + list.getLast()); //java
    }
    /*
        public void addFirst(E e) : 向集合首个位置添加元素
        public void addLast(E e) : 向集合尾部添加元素
     */
    public static void method() {
        //定义集合
        LinkedList<String> list = new LinkedList<>();
        //调用add方法添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        System.out.println("list:" + list); //[hello, world, java]
        //调用addFirst向集合的最开始添加元素
        list.addFirst("php");
        System.out.println("list:" + list); //[php, hello, world, java]
        //public void addLast(E e) : 向集合尾部添加元素
        list.addLast("python");
        System.out.println("list:" + list); //[php, hello, world, java, python]
    }
}

11. Set 接口的特点

/*
    Set接口是Collection下面的另一个子接口。

    Set接口有三个特点:
        1. 无序(怎么存,不一定怎么取)
        2. 没有索引(不能根据索引获取元素)
        3. 不可重复(不能存放重复元素)

    Set是一个接口,如果要用,需要使用实现类, Set接口下面最常用的实现类是HashSet
 */
public class Demo01Set {
    public static void main(String[] args) {
        //定义一个Set集合
        Set<String> set = new HashSet<>();
        //添加元素
        set.add("张三丰");
        set.add("张无忌");
        set.add("灭绝师太");
        set.add("金花婆婆");
        //输出
        //1. 无序(怎么存,不一定怎么取)
        System.out.println(set); //[灭绝师太, 张三丰, 张无忌, 金花婆婆]
        //2. 没有索引(不能根据索引获取元素)
        //System.out.println(set.get(1));
        //3. 不可重复(不能存放重复元素)
        set.add("灭绝师太");
        set.add("灭绝师太");
        set.add("灭绝师太");
        set.add("灭绝师太");
        set.add("灭绝师太");
        set.add("灭绝师太");
        System.out.println(set);
    }
}

12. HashSet的介绍以及遍历

/*
    如果要对Set集合进行遍历, 要么使用迭代器, 要么使用增强for。

    强烈推荐:增强for

    HashSet是Set下面最常用的实现类,满足Set接口所有的特点。
 */
public class Demo02Set {
    public static void main(String[] args) {
        //定义集合
        Set<String> set = new HashSet<>();
        //添加元素
        set.add("hello");
        set.add("world");
        set.add("java");
        set.add("php");
        //对集合进行遍历
        for(String s : set) {
            //s表示集合中的每一个元素
            System.out.println(s);
        }
    }
}

13. 对象和哈希值介绍以及如何获取到对象的哈希值

/*
    哈希值就是一个int数字, 我们可以把哈希值看出对象的一个标识(特征码)

    在Object中,有一个方法叫做hashCode,可以获取对象的哈希值。
    Object中的hashCode的哈希值是根据地址值计算的。

    如果想要自己定义哈希值的计算规则,可以重写hashCode方法。

    注意: 哈希值是对象的一个标识,但并不是一个唯一的标识,哈希值允许重复。

    总结:
        1. 哈希值是对象的一个特征码, 是一个int数字, 对象的哈希值允许重复。
        2. 调用对象的hashCode可以获取对象的哈希值,如果要自己定义哈希值的计算规则,那么需要重写hashCode方法。
 */
public class Demo01HashCode {
    public static void main(String[] args) {
        //创建Person对象
        Person p = new Person("柳岩", 38);
        //调用对象的hashCode,获取对象的哈希值。
        System.out.println(p.hashCode());

        Person p2 = new Person("柳岩", 38);
        System.out.println(p2.hashCode());

        Person p3 = new Person("白百合", 20);
        System.out.println(p3.hashCode());
    }
}
public class Person {
    private String name;
    private int age;

    //alt + insert

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    //重写hashCode,改变哈希值的计算规则
    //对象的哈希值一般根据属性去计算。如果两个对象的属性完全相同,那么哈希值应该一样。
    /*
    public int hashCode() {
        return name.hashCode() + age;
    }
    */

    public Person() {
    }

    public Person(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;
    }
}

14. 哈希表的介绍

参考 Java基础学习12:【List、Set、数据结构、Collections】中的图片。

15. HashSet判断唯一性的原因

参考 Java基础学习12:【List、Set、数据结构、Collections】中的图片。

16. HashSet存储自定义对象

/*
    HashSet判断唯一性的原理
        1. 先比较两个对象的哈希值。
            如果两个对象的哈希值不同,那么肯定不是同一个对象。
            如果两个对象的哈希值相同,不一定是同一个对象。
        2. 如果两个对象的哈希值相同,那么还需要调用equals方法进行比较。
            如果调用equals得到的结果是true,那么表示是同一个对象
            如果调用equals得到的结果是false,那么表示不是同一个对象

    要求: 使用HashSet存储Person对象, 并要求保证唯一性(如果两个对象的属性完全相同,那么就看成同一个对象)

    结论:如果使用HashSet存储自定义对象,并且要保证唯一性(如果两个对象的属性完全相同,那么就看成同一个对象),那么需要重写hashCode和equals方法
 */
public class Demo01HashSet {
    public static void main(String[] args) {
        //定义HashSet,用来保存Person
        Set<Person> set = new HashSet<>();
        //添加元素
        set.add(new Person("刘德华", 12));
        set.add(new Person("张学友", 22));
        set.add(new Person("郭富城", 32));

        set.add(new Person("刘德华", 12));

        //遍历并输出集合中的每一个元素
        for(Person p : set) {
            System.out.println(p);
        }
    }
}
public class Person {
    private String name;
    private int age;

    //alt + insert
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

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

    public Person() {
    }

    public Person(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;
    }
}

17. LinkedHashSet的特点

/*
    Set接口中还有一个实现类叫做LinkedHashSet

    LinkedHashSet内部除了有一个哈希表之外,还有一个链表,链表的作用是保证【有序】。

    Set接口是无序的,但是他不能保证所有的实现类都无序。
 */
public class Demo01LinkedHashSet {
    public static void main(String[] args) {
        //定义集合
        Set<String> set = new LinkedHashSet<>();
        //添加元素
        set.add("hello");
        set.add("world");
        set.add("java");
        set.add("php");
        //输出集合
        System.out.println(set);
    }
}

18. Collections中的shuffle方法

/*
    Collections 是一个工具类,是操作集合的工具类。

    常见方法:
        public static void shuffle(List<?> list) :打乱集合顺序
 */
public class Demo01Collections {
    public static void main(String[] args) {
        //定义集合
        ArrayList<String> list = new ArrayList<>();
        //添加元素
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("dd");
        //调用shuffle方法,打乱顺序
        Collections.shuffle(list);
        //输出
        System.out.println(list);
    }
}

19. Collections的自然排序

/*
    在Collections中,有一个方法,可以对集合中的内容进行排序。
        public static void sort(List list) :对集合中的内容进行排序

    要使用该sort方法排序的集合,对应的泛型必须实现Comparable接口。
    当一个类实现了Comparable接口后,就表示该类的对象具备了比较的功能,这种排序叫做自然排序

    公式: 升序就是我减他。
 */
public class Demo02Collections {
    public static void main(String[] args) {
        //定义集合,保存数字
        ArrayList<Integer> numList = new ArrayList<>();
        //添加数字
        numList.add(200);
        numList.add(100);
        numList.add(300);
        //调用sort方法,进行排序
        Collections.sort(numList);
        System.out.println("numList:" + numList);
        System.out.println("=======================");
        //定义集合保存字符串
        ArrayList<String> strList = new ArrayList<>();
        strList.add("bbb");
        strList.add("aaa");
        strList.add("ccc");
        //调用sort方法,对保存字符串的集合进行排序
        Collections.sort(strList);
        System.out.println("strList:" + strList);
        System.out.println("=======================");

        //定义集合,保存Person
        ArrayList<Person> personList = new ArrayList<>();
        //添加Person对象
        personList.add(new Person("柳岩", 36));
        personList.add(new Person("大幂幂", 26));
        personList.add(new Person("金星", 38));
        //对保存Person对象的集合进行排序
        Collections.sort(personList);
        System.out.println("personList:" + personList);
    }
}
public class Person implements Comparable<Person>{ //类实现Comparable接口后,就表示该类的对象具备了比较的功能。
    private String name;
    private int age;
    /*
        当我们使用Collections的sort方法对集合中的对象进行排序时, 系统会自动调用compareTo比较两个对象谁大谁小。
        比较的是调用者对象和参数对象。
        如果compareTo结果是正数,那么就表示调用者对象大于参数对象
        如果结果是0,表示两个对象相等
        如果compareTo结果是负数,那么就表示调用者对象小于参数对象。

        如果要排序公式:
            升序就是我(调用者)减他(参数)
            要根据什么排序,就使用什么属性相减。
     */
    @Override
    public int compareTo(Person o) {
        return this.getAge() - o.getAge();
    }

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

    public Person() {
    }

    public Person(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;
    }
}

20. Collections中的比较器排序

/*
    Collections中还有一个sort方法,可以进行比较器排序
       public static void sort(List list,Comparator c): 第一个参数表示要排序的集合,第二个参数表示比较器。

    如果一个类没有实现Comparable接口,那么表示该类的对象并不具备自己比较的功能,那么他们就不能自己排序。
    此时我们可以找一个法官帮他们去比较, 这个法官就是比较器。
    Comparator表示比较器。

    小结:
        自然排序指的是对象本身具备比较的功能,所以可以使用sort方法直接排序。            (Comparable)
        比较器排序指的是对象并不具备比较的功能,所以调用sort方法时还需要传递一个比较器   (Comparator)。
 */
public class Demo03Collections {
    public static void main(String[] args) {
        //定义集合
        ArrayList<Student> list = new ArrayList<>();
        //添加Student对象
        list.add(new Student("张三", 13));
        list.add(new Student("李四", 10));
        list.add(new Student("王叔叔", 15));
        //使用sort方法进行排序
        Collections.sort(list, new Rule());

        System.out.println("list:" + list);
    }
}
public class Student {
    private String name;
    private int age;

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

/*
    Comparator 表示比较器, 所以当Rule类实现该接口后,这个类表示的也是比较器
 */
public class Rule implements Comparator<Student>{
    /*
        当使用Collections的sort方法进行比较器排序时,内部会调用compare方法比较两个对象(o1和o2)
        如果compare方法返回值为正数,那么就表示第一个对象大于第二个对象。
        如果结果是0,那么表示两个对象相等。
        如果compare方法返回值为负数,那么就表示第二个对象大于第一个对象。

        如果要排序,公式为:
            升序就是一(第一个参数)减二(第二个参数)
     */
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getAge() - o2.getAge(); //根据学生的年龄升序排序。
    }
}
  • 资源分享QQ群
  • weinxin
  • 官方微信公众号
  • weinxin
沙海
C语言郝斌老师教程
动力节点最牛Java自学基础教程
一个Java基础入门的教程视频
C语言速查手册

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: