• Java集合框架【二容器[LinkedList容器类、Set接口]】


    一 LinkedList容器

    • LinkedList底层用双向链表实现的存储。
    • 特点:查询效率低,增删效率高,线程不安全双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。
      在这里插入图片描述
    class Node<E> {
    	E item;
    	Node<E> next;
    	Node<E> prev;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.1 LinkedList的使用(List接口)

    • Linked实现了List接口,所以LinkedList是具备List的存储特征的【有序、可重复】
    public class LInkedListTest {
        public static void main(String[] args) {
            LinkedList<String> list = new LinkedList<>();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("a");
            for(String s :list) {
                System.out.println(s);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    1.2 Linked的使用(非List标准)

    方法说明
    void addFirst(E e)将指定元素插入到开头
    void add Last(E e)将指定元素插入到结尾
    getFirst()返回此列表的第一个元素
    getLast()返回此列表的最后一个元素
    removeFirst()移除此列表中的第一个元素,并返回这个元素
    removeLast()移除此列表中的最后一个元素,并返回这个元素
    E pop()从此列表所表示的堆栈处弹出一个元素,等效于removeFirst
    voidpush(E e)将元素推入此列表所表示的堆栈这个等效于addFisrt(E e)
    booleanisEmpty()判断列表是否包含元素,如果不包含元素则返回true

    1.4 LinkedList源码分析

    • 节点类
    private static class Node<E> {
            E item;
            Node<E> next;
            Node<E> prev;
    
            Node(Node<E> prev, E element, Node<E> next) {
                this.item = element;
                this.next = next;
                this.prev = prev;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    二 Set接口

    • Set接口继承自Collection,Set接口中没有新增方法,方法和Collection保持完全一致。我们在前面通过List学习的方法,在Set中仍然适用。因此,学习Set的使用将没有任何难度。

    2.1 Set接口特点

    • Set特点:无序、不可重复无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。更确切地讲,新元素如果和Set中某个元素通过equals()方法对比为true,则只能保留一个。
    • Set常用的实现类有:HashSet、TreeSet等。

    2.2 HashSet容器类

    • Hashset是一个没有重复元素的集合,不保证元素的顺序。而且HashSet允许有null元素。HashSet是采用哈希算法实现,底层实际是用HashMap实现的(HashSet本质就是一个简化版的HashMap),因此,查询效率和增删效率都比较高。

    2.2.1 Hash算法原理

    • Hash算法也称之为散列算法
      在这里插入图片描述

    2.2.2 HashSet的例子

    /**
     * @author 缘友一世
     * date 2022/11/23-9:03
     */
    public class HashSetTest {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            set.add("a");
            set.add("d");
            set.add("b");
            set.add("a");
            //获取元素,在set容器中没有索引,没有对应的get方法。
            for(String s:set) {
                System.out.println(s);
            }
            boolean flag = set.remove("d");
            System.out.println(flag);
            for(String s:set) {
                System.out.println(s);
            }
            System.out.println(set.size());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    2.2.3 HashSet存储特征分析

    • Hashset是一个不保证元素的顺序且没有重复元素的集合,是线程不安全的。Hashset允许有null元素
      1. 无序:
        • 在HashSet中底层是使用HashMap存储元素的。
        • HashMap底层使用的是数组与链表实现元素的存储。
        • 元素在数组中存放时,并不是有序存放的也不是随机存放的,而是对元素的哈希值进行运算决定元素在数组中的位置。
      2. 不重复:
        • 当两个元素的哈希值进行运算后得到相同的在数组中的位置时,会调用元素的equals()方法判断两个元素是否相同。如果元素相同则不会添加该元素,如果不相同则会使用单向链表保存该元素。
    /**
     * @author 缘友一世
     * date 2022/11/23-9:11
     */
    public class Users {
        private String userName;
        private int userAge;
    
        public Users() {
        }
    
        public Users(String userName, int userAge) {
            this.userName = userName;
            this.userAge = userAge;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public int getUserAge() {
            return userAge;
        }
    
        public void setUserAge(int userAge) {
            this.userAge = userAge;
        }
    
        @Override
        public int hashCode() {
            int result=userName !=null ? userName.hashCode():0;
            result=31*result+userAge;
            return result;
        }
    
        @Override
        public boolean equals(Object o) {
            if(this==o) return true;
            if(o==null || getClass()!=o.getClass()) return false;
            Users users = (Users) o;
            if(userAge!=users.userAge) return false;
            return userName!=null ? userName.equals(users.userName):false;
        }
    
        @Override
        public String toString() {
            return "Users{" +
                    "userName='" + userName + '\'' +
                    ", userAge=" + userAge +
                    '}';
        }
    }
    
    class Test {
        public static void main(String[] args) {
            HashSet<Users> set1 = new HashSet<>();
            Users aaa = new Users("aaa", 19);
            Users bbb = new Users("aaa", 19);
            set1.add(aaa);
            set1.add(bbb);
            for(Users user:set1) {
                System.out.println(user);
            }
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    在这里插入图片描述

    2.3 TreeSet容器类

    • TreeSet是一个可以对元素进行排序的容器底层实际是用TreeMap实现的,***内部维持了一个简化版的TreeMap,通过key来存储Set的元素。***TreeSet内部需要对存储的元素进行排序,因此,我们需要给定排序规则。
    • 排序规则实现方式
      • 通过元素自身实现比较规则
      • 通过比较器指定比较规则
    /**
     * @author 缘友一世
     * date 2022/11/23-9:30
     */
    public class TreeSetTest {
        public static void main(String[] args) {
            TreeSet<String> set = new TreeSet<>();
            set.add("c");
            set.add("a");
            set.add("b");
            set.add("1");
            for(String str:set) {
                System.out.println(str);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述
    在这里插入图片描述

    2.4 通过元素自身实现比较规则

    • 在元素自身实现比较规则时,需要实现Comparable接口中的compareTo方法,该方法中用素定义比较规则。TreeSet通过调用该方法来完成对元素的排序处理。
    /**
     * @author 缘友一世
     * date 2022/11/23-12:53
     */
    public class SortTest {
        public static void main(String[] args) {
            TreeSet<Users2> set1 = new TreeSet<>();
            Users2 aaa = new Users2("aaa", 19);
            Users2 ccc = new Users2("ccc", 17);
            Users2 bbb = new Users2("bbb", 19);
            set1.add(aaa);
            set1.add(bbb);
            set1.add(ccc);
            for(Users2 user:set1) {
                System.out.println(user);
            }
        }
    }
    class Users2 implements Comparable<Users2> {
    
        private String userName;
        private int userAge;
    
        public Users2() {
        }
    
        public Users2(String userName, int userAge) {
            this.userName = userName;
            this.userAge = userAge;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public int getUserAge() {
            return userAge;
        }
    
        public void setUserAge(int userAge) {
            this.userAge = userAge;
        }
    
        @Override
        public int hashCode() {
            int result=userName !=null ? userName.hashCode():0;
            result=31*result+userAge;
            return result;
        }
    
    
    
        @Override
        public boolean equals(Object o) {
            if(this==o) return true;
            if(o==null || getClass()!=o.getClass()) return false;
            Users2 users = (Users2) o;
            if(userAge!=users.userAge) return false;
            return userName!=null ? userName.equals(users.userName):false;
        }
    
        @Override
        public String toString() {
            return "Users{" +
                    "userName='" + userName + '\'' +
                    ", userAge=" + userAge +
                    '}';
        }
    
        @Override
        public int compareTo(Users2 o) {
            if(this.userAge>o.getUserAge()) {
                return 1;
            }
            if(this.userAge==o.getUserAge()) {
                return this.userName.compareTo(o.getUserName());
            }
            return -1;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    在这里插入图片描述

    2.5 通过比较器实现比较规则

    • 通过比较器定义比较规则时,我们需要单独创建一个比较器,比较器需要实现Comparator接口中的compare方法来定义比较规则。
    • 在实例化TreeSet时将比较器对象交给TreeSet来完成元素的排序处理。此时元素自身就不需要实现比较规则了。
    
    /**
     * @author 缘友一世
     * date 2022/11/23-13:24
     */
    class Test {
        public static void main(String[]args){
            TreeSet<student> set = new TreeSet<>(new ComparatorTest());
            student ooo = new student("ooo", 18);
            student aaa = new student("aaa", 22);
            student sss = new student("sss", 22);
            set.add(ooo);
            set.add(aaa);
            set.add(sss);
            for(student x:set) {
                System.out.println(x);
            }
        }
    }
    public class ComparatorTest implements Comparator<student> {
        //定义比较规则
    
        @Override
        public int compare(student o1, student o2) {
            if(o1.getAge()>o2.getAge()) {//升序
                return 1;
            }else if(o1.getAge()==o2.getAge()) {
                return o1.getName().compareTo(o2.getName());
            }
            return -1;
        }
    }
    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 boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            student student = (student) o;
            return age == student.age && Objects.equals(name, student.name);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    
        @Override
        public String toString() {
            return "student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    在这里插入图片描述

    三 单例集合使用例子

    • 生成1-10之间的随机数(1-10),将不重复的10个随机数放到容器中

    List实现

    /**
     * @author 缘友一世
     * date 2022/11/23-13:36
     */
    public class SetDemo {
      public static void main(String[] args) {
      ArrayList<Integer> list = new ArrayList<>();
            while(true) {
                int num=(int)(Math.random()*10+1);
                if(!list.contains(num)) {
                    list.add(num);
                }
                if(list.size()==10) {
                    break;
                }
            }
            for(Integer x:list) {
                System.out.println(x);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    Set实现

    /**
     * @author 缘友一世
     * date 2022/11/23-13:36
     */
    public class SetDemo {
        public static void main(String[] args) {
            HashSet<Integer> set = new HashSet<>();
            while(true) {
                //set容器是不允许有重复元素的,所以不需要
                int num=(int)(Math.random()*10+1);
                set.add(num);
                if(set.size()==10) {
                    break;
                }
            }
            for(Integer i:set) {
                System.out.println(i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

  • 相关阅读:
    【C++ Primer Plus】第11章 使用类
    免费享受企业级安全:雷池社区版WAF,高效专业的Web安全的方案
    【疫情动态条形图】用Python开发全球疫情排名动态条形图bar_chart_race
    WebDAV与FTP的区别
    蓝桥杯-粘木棍-DFS
    单片机理论1
    通过钩子函数+Traceid实现Flask链路追踪
    slam从入门到精通(稍复杂一点的运动控制)
    [k8s] k8s基于csi使用rbd存储
    程序员脱单
  • 原文地址:https://blog.csdn.net/yang2330648064/article/details/127993320