JAVA集合

集合的理解和好处可以动态保存任意多个对象,使用比较方便!提供了一系列方便的操作对象的方法:add、remove、set、get等。使用集合添加,删除新元素的示意代码-简洁了。集合框架体系Collection单列集合集合package com.dnstudy.Collection_;import java.util.ArrayList;import java.util.List; //说明:以Arraylist实现类来演示public class Collect
摘要由CSDN通过智能技术生成
集合的理解和好处
  1. 可以动态保存任意多个对象,使用比较方便!
  2. 提供了一系列方便的操作对象的方法:add、remove、set、get等。
  3. 使用集合添加,删除新元素的示意代码-简洁了。

集合框架体系

Collection单列集合

集合在这里插入图片描述

package com.dnstudy.Collection_;

import java.util.ArrayList;
import java.util.List;
           //说明:以Arraylist实现类来演示
public class CollectionMethod {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        //add:添加单个元素
        list.add("jack");
        list.add(10); //list.add(new Integer(10))
        list.add(true);
        System.out.println("list = " + list);
        System.out.println("------------------------------------------");
        //remove:删除指定元素
        //list.remove(0); //删除第一个元素
        list.remove(true);//指定删除某个元素
        System.out.println("list = " + list);
        System.out.println("------------------------------------------");
        //contains:查找元素是否存在
        System.out.println(list.contains("jack"));//true
        System.out.println("------------------------------------------");
        //size:获取元素个数
        System.out.println(list.size()); //2
        System.out.println("------------------------------------------");
        //isEmpty:判断是否为空
        System.out.println(list.isEmpty()); // false
        System.out.println("------------------------------------------");
        //claer:清空
        list.clear();
        System.out.println("list = " + list);//list = []
        System.out.println("------------------------------------------");
        //addAll"添加多个元素
        ArrayList list2 = new ArrayList();
        list2.add("红楼梦");
        list2.add("三国演义");
        list.addAll(list2);
        System.out.println("list = " + list); //list = [红楼梦, 三国演义]
        System.out.println("------------------------------------------");
        //containsAll:查找多个元素是否都存在
        System.out.println(list.containsAll(list2));//true
        System.out.println("------------------------------------------");
        //removeAll:删除多个元素
        list.add("聊斋");
        list.removeAll(list2);
        System.out.println("list = " + list); //list = [聊斋]
    }
}
Collection接口和常用方法:
  • Collection接口遍历元素方式1-使用Iterator(迭代器)
  1. Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
  2. 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。
  3. Iterator仅用于遍历集合,Iterator本身并不存放对象。
  • Collection接口遍历对象方式2-for循环增强

​ 增强for循环,可以代替iterator迭代器,特点:增强for就是简化版的iterator,本质一样。只能用于遍历集合或数组。

基本语法:

for(元素类型 元素名 :集合名或数组名){

​ 访问元素

}

package com.dn.study.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class CollectionExercise {
@SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new Dog("小奥",3));
        list.add(new Dog("小熊",12));
        list.add(new Dog("小庄",30));
        //先使用for增强
    for(Object dog : list){
        System.out.println("dog = " + dog);
    }
    //使用迭代器
    System.out.println("----------------------使用迭代器来遍历------------------");
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        Object dog =  iterator.next();
        System.out.println("dog = " + dog);

    }
   }
}
List
  • List接口是Collection接口的子接口
    1. List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复。
    2. List集合中的每个元素都有其对应的顺序索引,即支持索引。
    3. List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
    4. JDK API中List接口的常用实现类有:ArrayList、LinkedList和Vector。
package com.dn.study.List;

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

public class ListExercise {
    public static void main(String[] args) {
        List list = new ArrayList();
        for (int i = 0; i < 8; i++){
            list.add("hello");
        }
        System.out.println("list = " + list);
        System.out.println("--------------------------------");
        list.add(1,"瓦吉吉哇");
        System.out.println("list = " + list);
        System.out.println("--------------------------------");
        System.out.println("获取第五个元素:" + list.get(4));//获取第五个元素:hello
        System.out.println("--------------------------------");
        list.remove(5);
        System.out.println("list = " + list);//list = [hello, 瓦吉吉哇, hello, hello, hello, hello, hello, hello]
        System.out.println("--------------------------------");
        //修改
        list.set(6,"红楼梦");
        System.out.println("list = " + list);//list = [hello, 瓦吉吉哇, hello, hello, hello, hello, 红楼梦,  hello]
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj =  iterator.next();
            System.out.println("obj = " + obj);
        }

    }

}

ArrayList

基本等同于Vector,线程不安全(执行效率高),在多线程情况下,不建议使用ArrayList

  1. ArrayList中维护了一个Object类型的数组elementsDate.transient Object[] elementData;
  2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
  3. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如需要扩容,则直接扩容elementData为1.5倍。
Vector

Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized。

在开发中,需要线程同步安全时,考虑使用Vector。

无参默认10,满后,就按2倍扩容。

如果指定大小,则每次直接按2倍扩。

LinkedList
底层结构
  1. LinkedList底层维护了一个双向链表。

  2. LinkedList中维护了两个属性first和last分别指向 首结点和尾结点。

  3. 每个结点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个结点。最终实现双向链表。

  4. 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。

全面说明

1.LinkedList底层实现了双向链表和双端队列特点

2.可以添加任意元素(元素可以重复),包括null

3.线程不安全,没有实现同步

ArrayList和LinkedList比较
底层结构增删的效率改查的效率
ArrayList可变数组较低 数组扩容较高
LinkedList双向链表较高,通过链表追加。较低
如何选择ArrarList和LinkedList:
  1. 如果我们改查的操作多,选择ArrayList
  2. 如果我们增删的操作多,选择LinkedList
  3. 一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
  4. 在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList,也就是说,要根据业务来进行选择
Set
  1. 无序(添加和取出的顺序不一致),没有索引
  2. 不允许重复元素,所以最多包含一个null
HashSet
  1. 实现了Set接口
  2. HashSet实际上是HashMap
public HashSet(){
    map = new HashMap<>();
}
  1. 可以存放null值,但是只能有一个null
  2. HashSet不保证元素是有序的,取决于hash后,再确定索引的结果
  3. 不能有重复的元素/对象
  • HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFactor)是0.75 = 12
  • 如果table数组使用到了临界值12,就会扩容到 16 * 2 = 32,新的临界值就是32*0.75=24,依次类推
  • 在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小 >=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制
LinkedHashSet
  1. LinkedHashSet是HashSet的子类
  2. LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表
  3. LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
  4. LinkedHashSet不允许添重复元素。
LinkeedHashSetSource
  1. 在LinkedHashSet中维护了一个hash表和双向链表(LinkedHashSet有head 和 tail)

  2. 每一个节点有before和after属性,这样可以形成双向链表

  3. 在添加一个元素时,先求hash值,再求索引,确定该元素在table的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加【原则和hashset一样】)。

    tail.next = newElement //示意代码
        newElement.pre = tail
        tail = newElement;
    
  4. 这样的话,我们遍历LinkedHashSet 也能确保插入顺序和遍历顺序一致

Map双列集合

在这里插入图片描述

Map
Map接口实现类的特点
  1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
  2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key不允许重复,原因和HashSet一样
  4. Map中的value可以重复
  5. Map的key可以为null,value也可以为null,注意key为null,只能有一个,value为null,可以多个。
  6. 常用String类作为Map的key
  7. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
package com.dn.study.Map;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
     * Map接口的使用
     * 特点:(1)存储键值对(2)键不能重复(3)无序
     */
public class Demo1 {
        public static void main(String[] args) {
            //创建Map集合
            Map<String, String> map = new HashMap<>();
            // 1. 添加元素
            map.put("cn", "中国");
            map.put("uk", "英国");
            map.put("usa", "美国");
            map.put("cn", "zhongguo");
            System.out.println("元素个数:" + map.size());
            System.out.println(map.toString());

            System.out.println("--------------------------------");
            //2. 删除
            map.remove("usa");
            System.out.println("删除之后:" + map.size());
            //3. 遍历
            //3.1使用keySet()
            System.out.println("------KeySet()-------------");
            //Set<String> keySet = map.keySet();
            for(String key : map.keySet()){
                System.out.println(key + "-----" + map.get(key));
            }
            //3.2使用entrySet()方法
            Set<Map.Entry<String, String>> entries = map.entrySet();
            for(Map.Entry<String, String> entry : entries){
                System.out.println(entry.getKey() + "-------------" + entry.getValue());
            }
            //4. 判断
            System.out.println(map.containsKey("cn")); // true
            System.out.println(map.containsValue("泰国")); // false

        }
}
HashMap
package com.dn.study.Map;

import java.util.HashMap;
import java.util.Map;

/**
 * HashMap集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 */
public class Demo2 {
    public static void main(String[] args) {
        //创建集合
        HashMap<Student, String> students = new HashMap<Student, String>();
        //添加元素
        Student s1 = new Student("孙悟空", 100);
        Student s2 = new Student("猪八戒", 101);
        Student s3 = new Student("沙和尚", 102);
        students.put(s1, "北京");
        students.put(s2, "上海");
        students.put(s3, "杭州");
       // students.put(s3, "南京");
        students.put(new Student("沙和尚", 102),"南京");
        System.out.println("元素个数:" + students.size());
        System.out.println(students.toString());

        System.out.println("-------------------删除---------------");
        //2 删除
        students.remove(s1);
        System.out.println("删除之后: " + students.size());
        System.out.println(students.toString());
        System.out.println("-------------遍历--------------------");
        //3.1使用keySet();
        for(Student key : students.keySet()){
            System.out.println(key.toString());
        }
        //3.2使用entrySet();
        for(Map.Entry<Student, String> entry : students.entrySet()){
            System.out.println(entry.getKey() +" ---------" + entry.getValue());
        }
        //4.判断
        System.out.println(students.containsKey(new Student("猪八戒", 101)));
        System.out.println(students.containsValue("杭州"));
    }

}

存储结构:哈希表
重复依据:键的hashCode()方法和equals方法

HashMap源码分析
 1 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // hashMap初始容量的大小
 2 static final int MAXIMUM_CAPACITY = 1 << 30; // hashMap的数组最大容量
 3 static final float DEFAULT_LOAD_FACTOR = 0.75f; //默认加载因子
 4 static final int TREEIFY_THRESHOLD = 8; // jdk1.8 当链表长度大于8时,调整成红黑树
 5 static final int UNTREEIFY_THRESHOLD = 6; // jdk1.8 当链表长度小于6时,调整成链表
 6 static final int MIN_TREEIFY_CAPACITY = 64; // jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树
 7 transient Node<K, V> [] table; //哈希表中的数组
 8 size; // 元素个数
无参构造
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // 加载因子
}
put方法
 public V put(K key, V value){
     return putVal(hash(key), key, value, false, true);
 }
总结
(1) HashMap刚创建时,table是null, 为了节省空间,当添加第一个元素时,table容量调整为16
(2)当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的·个数。
(3)jdk1.8 当链表长度大于8,并且元素个数大于等于64时,会调整成红黑树,目的提高执行效率
(4)jdk1.8 当链表长度小于6时,调整成链表
(5)jdk1.8以前, 链表是头插入,jdk1.8以后是尾插入
Map集合的实现类
  • HashMap【重点】

    • Jdk1.2版本,线程不安全,运行效率快;允许用null 作为key或是value。
  • Hashtable :

    • JDK1.0版本, 线程安全, 运行效率慢; 不允许null作为key或是value。
  • Properties :

    • Hashtable的子类, 要求key和value都是String。通常用于配置文件的读取。
  • TreeMap :

​ - 实现了SortedMap接口(是Map的子接口), 可以对key自动排序。

package com.dn.study.Map;

import java.util.Map;
import java.util.TreeMap;

/**
 * TreeMap的使用
 * 存储结构:红黑树
 */
public class Demo3 {
    public static void main(String[] args) {
        // 新建集合
        TreeMap<Student, String> treeMap = new TreeMap<Student, String>();
        // 1. 添加元素
        Student s1 = new Student("孙悟空", 100);
        Student s2 = new Student("猪八戒", 101);
        Student s3 = new Student("沙和尚", 102);
        treeMap.put(s1, "北京");
        treeMap.put(s2, "上海");
        treeMap.put(s3, "杭州");
        treeMap.put(new Student("沙和尚", 102), "南京");
        System.out.println("元素个数:" + treeMap.size());
        System.out.println(treeMap.toString());
        System.out.println("-----------------------------------");
        //2. 删除
       // treeMap.remove(new Student("猪八戒", 101));
        //System.out.println(treeMap.size());
        // 3. 遍历
        //3.1使用keySet
        for(Student key : treeMap.keySet()){
            System.out.println(key + " ------" + treeMap.get(key));
        }
        System.out.println("---------entrySet()--------------");
        for(Map.Entry<Student, String> entry : treeMap.entrySet()){
            System.out.println(entry.getKey()+ "-------" + entry.getValue());
        }
    }

}
Collection工具类
  • 概念:集合工具类,定义了除了存取以外的集合常用方法。

    • 方法

      • public static void reverse<List<?> list> //反转集合中元素的顺序

      • public static void reverse<List<?> list> //随机重置集合元素的顺序

      • public static void reverse<List<?> list> //升序排序(元素类型必须实现Comparable接口)

package com.dn.study.Map;

import java.util.*;

public class Demo4 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(5);
        list.add(2);
        list.add(30);
        list.add(6);
        //sort排序
        System.out.println("排序之前 :" + list.toString());
        Collections.sort(list);
        System.out.println("排序之后:" + list.toString());

        System.out.println( "---------------------");
        // binarySearch二分查找
        int i = Collections.binarySearch(list, 5);
        System.out.println(i);
        //copy复制
        List<Integer> dest = new ArrayList<>();
        for(int k = 0; k < list.size(); k++){
            dest.add(0);
        }
        Collections.copy(dest, list);
        System.out.println(dest.toString());

        //reverse反转
        Collections.reverse(list);
        System.out.println("反转之后:" + list.toString());

        //shuffle 打乱
        Collections.shuffle(list);
        System.out.println("打乱之后:" + list);

        // 补充: list转成数组
        Integer[] arr = list.toArray(new Integer[10]);
        System.out.println(arr.length);
        System.out.println(Arrays.toString(arr));
        //数组转成集合
        System.out.println("---------数组转成集合--------------------");
        String[] names = {"张三", "李四", "王五"};
        //集合是一个受限集合,不能添加和删除
        List<String> list2 = Arrays.asList(names);
        // list2.add("赵六");
        // list2.remove(0);
        System.out.println(list2);
        //把基本类型数组转成集合时, 需要修改为包装类型
        Integer[] nums = {100, 200, 300, 400, 500};
        List<Integer> list3 = Arrays.asList(nums);
        System.out.println(list3);
    }
}

集合总结:

  • 集合的概念:

​ 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法。

  • List集合:

    有序、有下标、元素可以重复。(ArrayList、LinkedList、Vector)

  • Set集合:

​ 无序、无下标、元素不可重复。(HashSet、TreeSet)

  • Map集合:

​ 存储一对数据,无序,无下标,键不可重复,值可重复。(HashMap, hashTable, TreeMap).

  • Collections:

    集合工具类,定义了除了存取以外的集合常用方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值