JavaSE之集合

# **一 Collection集合**
## **1.1 概述**
Collection是单列集合类的根接口,可以存储一系列符合某种规则的元素,该接口主要的子接口有
> `java.util.List`
> `java.util.Set`

List的主要特点是元素有序,可重复,Set的主要特点是元素无序,不重复,List集合的主要实现子类有
> `java.util.ArraysList`
> `java.util.LinkedList`

Set集合的常用子类有
> `java.util.HashSet`
> `java.util.TreeSet`

以及`java.util.HashSet`的子类
> `java.util.LinkedHashSet`

![](https://leanote.com/api/file/getImage?fileId=5d271f90ab6441780400316d)
# **二 List集合**
## **2.1 概述**
List集合是线性数据结构的主要实现,List接口继承于Collection接口,是单列集合的一个重要分支,常将实现于List接口的子类称为List集合,List集合元素以有序的线性结构存储,元素可以重复,支持使用索引来访问元素。
## **2.2 特点**
    

 - 有序,可重复。

    

 - 元素带有索引,可使用索引访问元素。

    

 - 访问速度快。
 
## **2.3 常用方法**
List不但拥有继承于Collection的通用方法,自身还增加了一些根据索引来操作元素的特有方法。(多态)

> - `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 ListDemo {
        public static void main(String[] args) {
            // 创建List集合对象
            List<String> list = new ArrayList<String>();
            
            // 往 尾部添加 指定元素
            list.add("图图");
            list.add("小美");
            list.add("不高兴");
            
            System.out.println(list);
            // add(int index,String s) 往指定位置添加
            list.add(1,"没头脑");
            
            System.out.println(list);
            // String remove(int index) 删除指定位置元素  返回被删除元素
            // 删除索引位置为2的元素 
            System.out.println("删除索引位置为2的元素");
            System.out.println(list.remove(2));
            
            System.out.println(list);
            
            // String set(int index,String s)
            // 在指定位置 进行 元素替代(改) 
            // 修改指定位置元素
            list.set(0, "三毛");
            System.out.println(list);
            
            // String get(int index)  获取指定位置元素
            
            // 跟size() 方法一起用  来 遍历的 
            for(int i = 0;i<list.size();i++){
                System.out.println(list.get(i));
            }
            //还可以使用增强for
            for (String string : list) {
                System.out.println(string);
            }      
        }
    }

## **2.4 List子类**
常用的子类有`ArraysList`和`LinkedList`,`Vetor`不常用,在jdk1.2之后已被替代,Vetor是同步的,即单线程。
### **2.4.1 ArraysList**
ArrayList是容量可以改变的非线程安全集合。内部实现使用数组结构存储,集合扩容时会创建更大的数组空间,快速随机访问速度快,增删慢,增删需要复制新数组对象,这个过程有可能需要移动其他的元素。
### **2.4.2 LinkedList**
LinkedList的本质是双向链表,插入和删除的速度比ArraysList快,随机访问速度慢,LinkedList集合还实现了Deque接口,具有队列与栈的性质。
![图片标题](https://leanote.com/api/file/getImage?fileId=5d272b66ab644176050033f4)

----------


实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而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 boolean isEmpty()`:如果列表不包含元素,则返回true。

LinkedList是List的子类,List中的方法LinkedList都是可以使用,这里就不做详细介绍,我们只需要了解LinkedList的特有方法即可。在开发时,LinkedList集合也可以作为堆栈,队列的结构使用。***(了解即可)***
方法演示:

    public class LinkedListDemo {
        public static void main(String[] args) {
            LinkedList<String> link = new LinkedList<String>();
            //添加元素
            link.addFirst("abc1");
            link.addFirst("abc2");
            link.addFirst("abc3");
            System.out.println(link);
            // 获取元素
            System.out.println(link.getFirst());
            System.out.println(link.getLast());
            // 删除元素
            System.out.println(link.removeFirst());
            System.out.println(link.removeLast());
    
            while (!link.isEmpty()) { //判断集合是否为空
                System.out.println(link.pop()); //弹出集合中的栈顶元素
            }
    
            System.out.println(link);
        }
    }
# **三 Set集合**
## 3.1 概述
Set集合也是继承于Collection接口,从方法上来看和Collection没什么区别,Set集合是无序且不允许重复的。常用的子类集合有HashSet,LinkedHashSet,TreeSet。
## **3.2 Set子类**
### **3.2.1 HashSet**
HashSet从源码分析是使用HashMap底层实现的,只是Value固定为一个静态对象,使用Key来保证元素的唯一性。

 - 数据结构(哈希表)
在jdk1.8之前,哈希表的底层是采用数组+链表实现的,即元素的hashCode值相同内容不同时,使用链表来存储元素,当元素较多时这种结构的查询速度就很慢;从jdk1.8开始,哈希表的底层采用数组+链表/红黑树实现,当元素hashCode值相同内容不相同时,优先使用链表结构存储,当相同hash值元素超过8个时转用红黑树结构存储,这样大大增强了查找元素的效率和速度。
 - 图示:
![图片标题](https://leanote.com/api/file/getImage?fileId=5d273133ab6441760500350b)

![图片标题](https://leanote.com/api/file/getImage?fileId=5d273923ab6441760500369e)

总而言之,**JDK1.8**引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

 - HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一

创建自定义Student类

    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 boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;
            Student student = (Student) o;
            return age == student.age &&
                   Objects.equals(name, student.name);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    }
    
    
    
    

>     public class HashSetDemo2 {
>         public static void main(String[] args) {
>             //创建集合对象   该集合中存储 Student类型对象
>             HashSet<Student> stuSet = new HashSet<Student>();
>             //存储 
>             Student stu = new Student("于谦", 43);
>             stuSet.add(stu);
>             stuSet.add(new Student("郭德纲", 44));
>             stuSet.add(new Student("于谦", 43));
>             stuSet.add(new Student("郭麒麟", 23));
>             stuSet.add(stu);
>     
>             for (Student stu2 : stuSet) {
>                 System.out.println(stu2);
>             }
>         }
>     }
>     执行结果:
>     Student [name=郭德纲, age=44]
>     Student [name=于谦, age=43]
>     Student [name=郭麒麟, age=23]

### **3.2.2 LinkedHashSet**
LinkedHashSet继承于HashSet,具有HashSet特点,只不过使用链表来维护了元素插入顺序。链表+哈希表结构

### **3.2.3 TreeSet**
TreeSet从源码上来分析是使用TreeMap来实现的,底层为树结构,在添加新元素到集合中时,按照某种比较规则将其插入合适的位置,保证插入后的集合仍然是有序的。
# **四 Map集合**
## **4.1 概述**
Map集合是以key-Value键值对作为存储元素实现的哈希结构,Key是通过某种哈希函数计算后来保证唯一性的,Value则可以重复。
![图片标题](https://leanote.com/api/file/getImage?fileId=5d274aafab64417804003a03)
## **4.2 Map子类**
### **4.2.1 HashMap**
HashMap底层数据结构为哈希表(jdk1.8之后哈希表采用数组+链表/红黑树结构),key通过计算hashCode来保证唯一性,值可以重复,非线程安全,插入和取出的顺序可能会不一致。
### **4.2.2 LinkedHashMap**
LinkedHashMap继承于HashMap集合,数据结构为链表+哈希表,相比HashMap,LinkedHashMap使用链表来维护插入顺序。增删性能强于HashMap,查询性能略逊于HashMap。
### **4.2.3 HashTable**
jdk1.0中引入的哈希表集合,单线程同步,以全互斥方式处理并发情况,性能较差。
### **4.2.4 ConcurrentHashMap**
高并发情况下推荐使用ConcurrentHashMap,jdk5中引入的线程安全的哈希表集合,在jdk8之前采用了分段锁的设计理念,相当于HashTable与HashMap的折中版本,效率与一致性权衡后的结果,在多线程并发场景中,优先推荐使用。
在jdk11中对jdk7进行了改造:

 - 取消了分段锁机制,进一步降低冲突概率
 - 引入红黑树结构
 - 使用了更加优化的方式统计集合内的元素数量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值