Java集合

1、集合

总结:集合和数组类似,是一种用于存储元素的可变长容器,

集合与数组的区别:

  • 集合的长度可变,数组长度不可变

  • Array能够存储基本数据类型和对象类型,而ArrayList只能存储对象类型

  • Array存储的是同一类型的数据,ArrayList可以存储多种类型,但只能是对象类型

集合的体系:

集合分为单例集合与双例集合,两类的父亲接口下有许多实现类,不同的实现类所用的数据结构与算法都不一样

1.1、集合扩列

List集合的底层实现是数组结构,而数组的大小是不可改变的,当容器的内存不足时,就需要进行扩容,扩容的方法:重新分配一个新的数组,然后复制元素到新的数组中,再将新添加的元素添加到数组末位

  1. ArrayList 初始大小:10; 扩容机制:当发现容量不足时扩容,容量为原来的1.5倍+1。

  2. LinkedList 初始大小:0; 扩容机制:无。

  3. Vector 初始大小:10; 扩容机制:当发现容量不足时,扩容到原来的两倍

  4. HashSet 初始大小:16; 扩容机制:加载因子为0.75,当超过这个阈值时扩容,扩容到原来的两倍。它的子链表达到8时 ,转化成红黑树。小于6个时转化成链表。

  5. HashMap 初始大小:16; 扩容机制:加载因子为0.75,当超过这个阈值时扩容,扩容到原来的两倍。它的子链表达到8时 ,转化成红黑树。小于6个时转化成链表。

  6. Hashtable 初始大小:11; 扩容机制:加载因子为0.75,当超过这个阈值时扩容,扩容为2*原数组长度+1。

1.2、集合的线程安全

  • 线程安全

    1. vector

    2. HashTable

  • 线程不安全

    1. ArrayList

    2. LikedList

    3. HashMap

2、单例集合

2.1、List接口

  • 概述:List是一个接口,下面主要有三个个实现类ArrayList和LinkedList和Vector

  • 特点:

    • List接口存储的数据为有序排列的,存储的时候是什么顺序,取出来就是什么顺序(1、2、3、4、5)

    • List结构为每一个存储的元素分配了一个索引,通过索引可以精准的访问每一个指定的元素,可以取代数组

    • List接口存储的数据允许重复

    • 只有Vector是线程安全的

2.1.1、ArrayList集合

特点:因为底层采用数组的数据结构实现,所以查询速度快,增删较慢,需要开辟连续的空间,且线程不安全

常用的方法(由图可知,List是Collection,则List继承Collection中的方法,除此之外还有很多List自身的方法)

  • public boolean add(int index, E element): 将指定的元素,添加到该集合中的指定位置上

  • public E get(int index):返回集合中指定位置的元素。

  • public object remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。

  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

public class Demo01 {
    public static void main(String[] args) {
        // 创建List集合对象
        List cities = new ArrayList<String>();

        cities.add("济南");         // 索引: 0
        cities.add("石家庄");        // 索引: 1
        cities.add("昆明");         // 索引: 2

        System.out.println(cities);     // [济南, 石家庄, 昆明]
        cities.add(1, "福州");      		// 原来的元素往后推

        System.out.println(cities);         // [济南, 福州, 石家庄, 昆明]

        // 删除索引位置为2的元素,返回被删除元素
        System.out.println(cities.remove(2));           // 石家庄

        System.out.println(cities);            // [济南, 福州, 昆明]

        // 在指定位置 进行 元素替代(改)
        cities.set(0, "银川");
        System.out.println(cities);             // [银川, 福州, 昆明]

        // 获取指定位置元素
        System.out.println(cities.get(0));      // 银川

        System.out.println("---------");
        // 跟size() 方法一起用  来 遍历的
        for (int i = 0; i < cities.size(); i++) {
            System.out.println(cities.get(i));
        }

        System.out.println("---------");
        //还可以使用增强for
        for (Object city : cities) {
            System.out.println(city);
        }
    }
}

 

2.1.2、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

public class Demo02 {
    public static void main(String[] args) {
        LinkedList cities = new LinkedList<String>();

        // 添加元素到头部
        cities.addFirst("广西");      // cities: [广西]
        cities.addFirst("陕西");      // cities: [陕西, 广西]
        cities.addFirst("山西");      // cities: [山西, 陕西, 广西]
        cities.addFirst("江西");      // cities: [江西, 山西, 陕西, 广西]

        System.out.println(cities);                 // [江西, 山西, 陕西, 广西]

        // 获取链表头部元素
        System.out.println(cities.getFirst());      // 江西

        // 获取链表尾部元素
        System.out.println(cities.getLast());       // 广西

        // 删除链表头部元素并返回
        System.out.println(cities.removeFirst());   // 江西

        // 删除链表尾部元素并返回
        System.out.println(cities.removeLast());   // 广西

        System.out.println(cities);                 // [山西, 陕西]
    }
}

LinkedList与ArrayList:

  1. LinkedList数据结构是双向循环链表,ArrayList的数据结构是数组

  2. LinkedList不支持随机访问,ArrayList支持随机访问

2.2、Set接口和实现类

特点:无序、无下限、元素不可重复,方法全部来自于父类Collection,没有什么 功能上的扩充

2.2.1、HashSet集合

特点:

  • 是Set接口的一个实现类

  • 无序,元素不可重复

  • 底层是一个HasMap,HashSet的值存放再HashMap的Key上

去重原理:HashSet根据对象的哈希值来确定元素再集合中的存储位置,因此具有良好的存储和查找性能,当存入元素时会调用对象的hashCode()方法计算该对象的hash值,当哈希码相同时(可能为hash冲突), 会调用equals()方法来进行确认(确认的是对象内存的地址值),结果为true则拒绝存入

public class Demo01 {
    public static void main(String[] args) {
        //创建 Set集合
        HashSet set = new HashSet<String>();

        //添加元素
        set.add(new String("河北"));
        set.add("湖北");
        set.add("河北");
        set.add("湖北");

        //遍历
        for (Object name : set) {
            System.out.println(name);
        }
    }
}

注意:HashSet在Jdk8以后底层采用了数组+链表+红黑树;当HashSet存储的数据太多,数组的容量达到64且链表长度大于阈值8时,会将数组上的链表转化为红黑树,以降低查询时间

2.2.2、TreeSet集合

与HashSet一样,为不可重复且无序,但TreeSet可以根据一定的排序规则对元素进行排序,需要注意的时,TreeSet存储的元素必须实现Comparable接口(一些类型以及实现了,比如String),否则会抛出异常

2.3、Iterator

概念:Iterator:一种设计模式,是一个对象,可以用来遍历序列中的对象

使用for-each遍历集合序列时,如果要改变序列中的值,要使用iterator,否则会报错;原因是for-each本质是使用iterator进行遍历,iterator在使用next获取下一个元素时,会先检查序列中的值有没有被改变,如果改变就会抛出错误

3、双例集合

特点:

  • 存储一堆数据、无序、无下标、键key不可以重复,值value可以

  • 用于保存具有映射关系的键值对

  • HashMap对于Key的去重原理采用的是哈希算法,即计算元素的哈希值hashcode(),再判断是否使用equals方法

常用方法:

  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。

  • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。

  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。

  • boolean containsKey(Object key) 判断集合中是否包含指定的键。

  • public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。

  • public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。

数据存储实例:

public class Demo01 {
    public static void main(String[] args) {
        //创建 map对象
        HashMap<String, String> map = new HashMap();

        //添加元素到集合
        map.put("江西", "南昌");
        map.put("湖南", "长沙");
        map.put("湖北", "武汉");
        
        // 存取是无序的
        System.out.println(map);        //  {湖南=长沙, 湖北=武汉, 江西=南昌}

        // String remove(String key): 根据key来删除记录,并将key对应的value返回
        System.out.println(map.remove("江西"));       // 南昌

        System.out.println(map);            // {湖南=长沙, 湖北=武汉}

        // 查看 湖北的省会 是哪座城市
        System.out.println(map.get("湖北"));  // 武汉
        System.out.println(map.get("湖南"));  // 长沙
    }
}

数据遍历实例:

使用方法:

  • public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。

  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。

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

        Map<String, String> cities = new HashMap<>();

        //添加元素到集合
        cities.put("广西", "南宁");
        cities.put("云南", "昆明");
        cities.put("贵州", "贵阳");

        // 1.获取key的集合
        Set<String> provinces = cities.keySet();       // [贵州, 广西, 云南]
        System.out.println(provinces);

        // 2.遍历key的集合
        for (String province : provinces) {

            // 3.根据key(省份)拿到value(省会城市)
            String city = cities.get(province);
            System.out.println(province + "省的省会是:" + city);
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值