Java集合 (上 单列集合:Collection、List、ArrayList、LinkedList、Set、HashSet、LinkedHashSet、TreeSet)

一、集合简介

1.1、集合的定义

集合是一种容器,用来装数据的,类似于数组,但集合的大小可变,开发中也非常常用。为了满足不同的业务场景需求,JAVA给我们提供了不同特点的集合给我们选择。

1.2、集合体系结构

  • Collection代表单列集合,每个元素(数据)只包含一个值。
  • Map代表双列集合,每个元素包含两个值(键值对)。

Collection集合特点:

  • List系列集合添加的元素是有序、可重复、有索引。
  1. ArrayList、LinekdList :有序、可重复、有索引。
  • Set系列集合添加的元素是无序、不重复、无索引。
  1. HashSet: 无序、不重复、无索引;
  2. LinkedHashSet: 有序、不重复、无索引。
  3. TreeSet:按照大小默认升序排序、不重复、无索引。

二、Collection集合

为啥要先学Collection的常用方法?

Collection是单列集合的祖宗,它规定的方法(功能)是全部单列集合都会继承的。

2.1、Collection的常见方法

例子:常见方法的演示
package com.itheima.d1_collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.IntFunction;

/**
    目标:掌握Collection集合的常用API.
    Collection是集合的祖宗类,它的功能是全部集合都可以继承使用的,所以要学习它。
    Collection API如下:
         - public boolean add(E e):  把给定的对象添加到当前集合中 。
         - public void clear() :清空集合中所有的元素。
         - public boolean remove(E e): 把给定的对象在当前集合中删除。
         - public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。
         - public boolean isEmpty(): 判断当前集合是否为空。
         - public int size(): 返回集合中元素的个数。
         - public Object[] toArray(): 把集合中的元素,存储到数组中。
 */
public class CollectionTest2API {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>(); // 多态写法
        // 1.public boolean add(E e):添加元素, 添加成功返回true。
        c.add("java1");
        c.add("java1");
        c.add("java2");
        c.add("java2");
        c.add("java3");
        System.out.println(c);

        // 2.public void clear():清空集合的元素。
        //c.clear();
        //System.out.println(c);

        // 3.public boolean isEmpty():判断集合是否为空 是空返回true,反之。
        System.out.println(c.isEmpty()); // false

        // 4.public int size():获取集合的大小。
        System.out.println(c.size());

        // 5.public boolean contains(Object obj):判断集合中是否包含某个元素。
        System.out.println(c.contains("java1")); // true
        System.out.println(c.contains("Java1")); // false

        // 6.public boolean remove(E e):删除某个元素:如果有多个重复元素默认删除前面的第一个!
        System.out.println(c.remove("java1"));
        System.out.println(c);

        // 7.public Object[] toArray():把集合转换成数组
        Object[] arr = c.toArray();
        System.out.println(Arrays.toString(arr));

        String[] arr2 = c.toArray(new String[c.size()]);
        System.out.println(Arrays.toString(arr2));

        System.out.println("--------------------------------------------");
        // 把一个集合的全部数据倒入到另一个集合中去。
        Collection<String> c1 = new ArrayList<>();
        c1.add("java1");
        c1.add("java2");
        Collection<String> c2 = new ArrayList<>();
        c2.add("java3");
        c2.add("java4");
        c1.addAll(c2); // 就是把c2集合的全部数据倒入到c1集合中去。
        System.out.println(c1);
        System.out.println(c2);
    }
}

2.2、Collection的遍历方式

2.2.1、迭代器

例子:迭代器演示
package com.itheima.d2_collection_traverse;

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

/**
    目标:Collection集合的遍历方式一:使迭代器Iterator遍历
 */
public class CollectionDemo01 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("素素");
        // c.add("灭绝");
        System.out.println(c);
        // c = [赵敏, 小昭, 素素]
        //                       it

        // 使用迭代器遍历集合
        // 1、从集合对象中获取迭代器对象。
        Iterator<String> it = c.iterator();
//        System.out.println(it.next());
//        System.out.println(it.next());
//        System.out.println(it.next());
//        System.out.println(it.next());
        // System.out.println(it.next()); // 出现异常的

        // 2、我们应该使用循环结合迭代器遍历集合。
        while (it.hasNext()){//当前位置是否有值
            String ele = it.next();
            System.out.println(ele);

        }

    }
}

2.2.2、增强for循环

例子:增强for循演示
package com.itheima.d2_collection_traverse;
import java.util.ArrayList;
import java.util.Collection;
/**
     目标:Collection集合的遍历方式二:增强for
 */
public class CollectionDemo02 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("素素");
        c.add("灭绝");
        System.out.println(c);
        // c = [赵敏, 小昭, 素素, 灭绝]
        //                      ele

        // 使用增强for遍历集合或者数组。
        for (String ele : c) {
            System.out.println(ele);
        }

        String[] names = {"迪丽热巴", "古力娜扎", "稀奇哈哈"};
        for (String name : names) {
            System.out.println(name);
        }

    }
}

2.2.3、Lambda表达式

package com.itheima.d2_collection_traverse;
import java.util.ArrayList;
import java.util.Collection;

/**
     目标:Collection集合的遍历方式三:JDK8开始新增的Lambda表达式。
 */
public class CollectionDemo03 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("殷素素");
        c.add("周芷若");
        System.out.println(c);
        // [赵敏, 小昭, 殷素素, 周芷若]
        //                     s

        // default void forEach(Consumer<? super T> action):  结合Lambda表达式遍历集合:
//        c.forEach(new Consumer<String>() {
//            @Override
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        });
//
//        c.forEach((String s) -> {
//                System.out.println(s);
//        });
//
//        c.forEach(s  -> {
//            System.out.println(s);
//        });
//
//        c.forEach(s  -> System.out.println(s) );

        c.forEach(System.out::println );
    }
}

三、List集合

3.1、List集合的特有方法和遍历方式

3.1.1、List集合的特有方法

package com.itheima.d3_collection_list;

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

/**
      目标:掌握List系列集合的特点,以及其提供的特有方法。
 */
public class ListTest1 {
    public static void main(String[] args) {
        // 1.创建一个ArrayList集合对象(有序、可重复、有索引)
        List<String> list = new ArrayList<>();  // 一行经典代码
        list.add("蜘蛛精");
        list.add("至尊宝");
        list.add("至尊宝");
        list.add("牛夫人");
        System.out.println(list); // [蜘蛛精, 至尊宝, 至尊宝, 牛夫人]

        // 2.public void add(int index, E element): 在某个索引位置插入元素。
        list.add(2, "紫霞仙子");
        System.out.println(list);

        // 3.public E remove(int index): 根据索引删除元素,返回被删除元素
        System.out.println(list.remove(2));
        System.out.println(list);

        // 4.public E get(int index): 返回集合中指定位置的元素。
        System.out.println(list.get(3));

        // 5.public E set(int index, E element): 修改索引位置处的元素,修改成功后,会返回原来的数据
        System.out.println(list.set(3, "牛魔王"));
        System.out.println(list);
    }
}

3.1.2、List集合支持的遍历方式

package com.itheima.d3_collection_list;

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

/**
    拓展:List系列集合的遍历方式.

    List遍历方式:
        (1)for循环。(独有的,因为List有索引)。
        (2)迭代器。
        (3)foreach。
        (4)JDK 1.8新技术。

 */
public class ListTest2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("糖宝宝");
        list.add("蜘蛛精");
        list.add("至尊宝");

        //(1)for循环
        for (int i = 0; i < list.size(); i++) {
            // i = 0 1 2
            String s = list.get(i);
            System.out.println(s);
        }

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

        //(3)增强for循环(foreach遍历)
        for (String s : list) {
            System.out.println(s);
        }

        //(4)JDK 1.8开始之后的Lambda表达式
        list.forEach(s -> {
            System.out.println(s);
        });
    }
}

 3.2、ArrayList集合

3.2.1、ArrayList集合的底层原理

3.2.2、ArrayList集合适合的应用场景

3.3、LinkedList集合

3.3.1、LinkedList集合的底层原理

  • 基于双链表实现

3.3.2、LinkedList集合的特有方法

 3.3.3、LinkedList集合的应用场景

1、用来设计队列;    2、用来设计栈

package com.itheima.d3_collection_list;

import java.util.LinkedList;

/**
 * 目标:掌握LinkedList集合的使用。
 */
public class ListTest3 {
    public static void main(String[] args) {
        // 1、创建一个队列。
        LinkedList<String> queue = new LinkedList<>();
        // 入队
        queue.addLast("第1号人");
        queue.addLast("第2号人");
        queue.addLast("第3号人");
        queue.addLast("第4号人");
        System.out.println(queue);
        // 出队
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue);
        System.out.println("--------------------------------------------------");
        // 2、创建一个栈对象。
        LinkedList<String> stack = new LinkedList<>();
        // 压栈(push)
        stack.push("第1颗子弹");
        stack.push("第2颗子弹");
        stack.push("第3颗子弹");
        stack.push("第4颗子弹");
        System.out.println(stack);
        // 出栈(pop)
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack);
    }
}

四、Set系列集合

Set系列集合的特点:

 4.1、HashSet集合

4.1.1、HashSet集合的底层原理

 

(当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍)

 4.1.2、深入理解HashSet集合去重复的机制

结论:如果希望Set集合认为2个内容一样的对象是重复的,必须重写对象的hashCode()equals()方法

例子:相同内容的不同对象如何判定是重复的?

package com.itheima.d4_collection_set;

import java.util.Objects;

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

    public Student() {
    }

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

    // 只要两个对象内容一样就返回true
    @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 && Double.compare(student.height, height) == 0 && Objects.equals(name, student.name);
    }

    // 只要两个对象内容一样,返回的哈希值就是一样的。
    @Override
    public int hashCode() {
        // 姓名 年龄 身高计算哈希值的
        return Objects.hash(name, age, height);
    }

    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 double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

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

4.2、LinkedHashSet集合

LinkedHashSet:有序、不重复、无索引。

4.3、TreeSet集合

方式一:

package com.itheima.d4_collection_set;

import java.util.Objects;

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


    public Student() {
    }

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

    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 double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

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

    @Override
    public int compareTo(Student o) {
        // 如果认为左边对象大于右边对象返回正整数
        // 如果认为左边对象小于右边对象返回负整数
        // 如果认为左边对象等于右边对象返回0
        // 需求:按照年龄升序排序、
        return this.age - o.age;
    }
}
package com.itheima.d4_collection_set;

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

public class SetTest4 {
    public static void main(String[] args) {
        Set<Integer> set1 = new TreeSet<>();
        set1.add(6);
        set1.add(5);
        set1.add(5);
        set1.add(7);
        System.out.println(set1);//[5, 6, 7]

        Set<Student> students=new TreeSet<>();
        students.add(new Student("蜘蛛精",23, 169.7));
        students.add(new Student("紫霞",22, 169.8));
        students.add(new Student("至尊宝",26, 165.5));
        students.add(new Student("牛魔王",22, 183.5));
        System.out.println(students);//[Student{name='紫霞', age=22, height=169.8}, Student{name='蜘蛛精', age=23, height=169.7}, Student{name='至尊宝', age=26, height=165.5}]
    }
}

方式二:

package com.itheima.d4_collection_set;

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

public class SetTest4 {
    public static void main(String[] args) {
        Set<Integer> set1 = new TreeSet<>();
        set1.add(6);
        set1.add(5);
        set1.add(5);
        set1.add(7);
        System.out.println(set1);//[5, 6, 7]

//        Set<Student> students=new TreeSet<>(new Comparator<Student>() {
//            @Override
//            public int compare(Student o1, Student o2) {
//                return Double.compare(o1.getHeight(), o2.getHeight());
//            }
//        });
        Set<Student> students = new TreeSet<>(( o1,  o2) ->  Double.compare(o1.getHeight() , o2.getHeight()));

        students.add(new Student("蜘蛛精",23, 169.7));
        students.add(new Student("紫霞",22, 169.8));
        students.add(new Student("至尊宝",26, 165.5));
        students.add(new Student("牛魔王",22, 183.5));
        System.out.println(students);
//[Student{name='至尊宝', age=26, height=165.5}, Student{name='蜘蛛精', age=23, height=169.7}, Student{name='紫霞', age=22, height=169.8}, Student{name='牛魔王', age=22, height=183.5}]
    }
}

五、总结

 

例子:集合的并发修改异常

package com.itheima.d5_collection_exception;

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

public class CollectionTest1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("王麻子");
        list.add("小李子");
        list.add("李爱花");
        list.add("张全蛋");
        list.add("晓李");
        list.add("李玉刚");
        System.out.println(list);//[王麻子, 小李子, 李爱花, 张全蛋, 晓李, 李玉刚]

        // 需求:找出集合中全部带“李”的名字,并从集合中删除。


//错误方法1:
        //使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String name = it.next();
            if(name.contains("李")){
                list.remove(name);
            }
        }
        System.out.println(list);//异常


//错误方法2:
        // 使用增强for循环遍历集合并删除数据,没有办法解决bug.
        for (String name : list) {
            if(name.contains("李")){
                list.remove(name);
            }
        }
        System.out.println(list);//异常


//错误方法3:
        //Lambda表达式
        list.forEach(name -> {
            if(name.contains("李")){
                list.remove(name);
            }
        });
        System.out.println(list);//异常
    }
}

正确方法
例子:使用for循环遍历集合并删除集合中带李字的名字
for (int i = 0; i < list.size(); i++) {
            String name = list.get(i);
            if(name.contains("李")){
                list.remove(name);
            }
        }
        System.out.println(list);//[王麻子, 李爱花, 张全蛋, 李玉刚]
//结果漏掉了一些数据,怎么解决呢?

        //1. 使用for循环遍历集合并删除集合中带李字的名字
        //  [王麻子, 小李子, 李爱花, 张全蛋, 晓李, 李玉刚]
        //  [王麻子, 张全蛋]
        for (int i = 0; i < list.size(); i++) {
            String name = list.get(i);
            if(name.contains("李")){
                list.remove(name);
                i--;
            }
        }
        System.out.println(list);//[王麻子, 张全蛋]
        //2. 倒着去删除也是可以的。

        //3.使用构造器中的it.remove()
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String name = it.next();
            if(name.contains("李")){
                // list.remove(name); // 并发修改异常的错误。
                it.remove(); // 删除迭代器当前遍历到的数据,每删除一个数据后,相当于也在底层做了i--
            }
        }
        System.out.println(list);//[王麻子, 张全蛋]

 六、Collection的其它相关知识

6.1、前置知识:可变参数

例子:可变参数的演示
import java.util.Arrays;

/**
 * 目标:认识可变参数,掌握其作用。
 */
public class ParamTest {
    public static void main(String[] args) {
        // 特点:
        test(); // 不传数据
        test(10); // 传输一个数据给它
        test(10, 20, 30); // 传输多个数据给它
        test(new int[]{10, 20, 30, 40}); // 传输一个数组给可变参数
    }

    // 注意事项1:一个形参列表中,只能有一个可变参数。
    // 注意事项2:可变参数必须放在形参列表的最后面
    public static void test(int...nums){
        // 可变参数在方法内部,本质就是一个数组。
        System.out.println(nums.length);
        System.out.println(Arrays.toString(nums));
        System.out.println("-----------------------------------------");
    }
}

6.2、Collections工具类

例子:Student类,并自定义类型必须实现了Comparable接口
package com.itheima.d2_collections;

import java.util.Objects;

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

    // this  o
    @Override
    public int compareTo(Student o) {
        // 如果认为左边对象大于右边对象返回正整数
        // 如果认为左边对象小于右边对象返回负整数
        // 如果认为左边对象等于右边对象返回0
        // 需求:按照年龄升序排序、
        return this.age - o.age;
    }

    public Student() {
    }

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

    // 只要两个对象内容一样就返回true
    @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 && Double.compare(student.height, height) == 0 && Objects.equals(name, student.name);
    }

    // 只要两个对象内容一样,返回的哈希值就是一样的。
    @Override
    public int hashCode() {
        // 姓名 年龄 身高计算哈希值的
        return Objects.hash(name, age, height);
    }

    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 double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}
package com.itheima.d2_collections;

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

/**
 * 目标:掌握Collections集合工具类的使用。
 */
public class CollectionsTest1 {
    public static void main(String[] args) {
        // 1、public static <T> boolean addAll(Collection<? super T> c, T...elements):为集合批量添加数据
        List<String> names = new ArrayList<>();
        Collections.addAll(names, "张三", "王五", "李四", "张麻子");
        System.out.println(names);

        // 2、public static void shuffle(List<?> list):打乱List集合中的元素顺序。
        Collections.shuffle(names);
        System.out.println(names);

        // 3、 public static <T> void sort(List<T> list):对List集合中的元素进行升序排序。
        List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(5);
        list.add(2);
        Collections.sort(list);
        System.out.println(list);

        List<Student> students = new ArrayList<>();
        students.add(new Student("蜘蛛精",23, 169.7));
        students.add(new Student("紫霞",22, 169.8));
        students.add(new Student("紫霞",22, 169.8));
        students.add(new Student("至尊宝",26, 165.5));
        // Collections.sort(students);  //要自定义类型必须实现了Comparable接口,并指定比较规则
        // System.out.println(students);

        // 4、public static <T> void sort(List<T> list, Comparator<? super T> c): 对List集合中元素,按照比较器对象指定的规则进行排序
        Collections.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return Double.compare(o1.getHeight(), o2.getHeight());
            }
        });
        System.out.println(students);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值