• 集合java


    java集合

    在这里插入图片描述
    集合、数组都是对多个数据进行存储操作的结构,简称Java容器
    此时的存储,主要是指内存层面的存储,不涉及持久化的存储(txt,jpg,avi)

    Java集合可分为Collection 和 Map 两种体系

    1. Collection接口:单列数据,定义了存取一组对象方法的集合

    List : 元素有序、可重复的集合 -->动态数组
    ArratList、LinkedList、Vector
    Set:元素无序、不可重复的集合 -->数学中的集合
    HashSet、LinkedHashSet、TreeSet

    2.Map接口:双列数据、保存具有映射关系"key-value"的集合 -->高中函数、不能一个key 对应两个value。python中的字典

    HashMap、LinkedHashMap、TreeMap、Hashtable、Properties

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

    Collection 接口中的API(都在代码里有注释了)

    package Collection;
    
    import java.awt.List;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Date;
    import org.junit.Test;
    
    public class CollectionTest {
    	@Test
    
    	// 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类重写equals。否则Obj里面比的是地址
    	public void test1(){
    		Collection coll = new ArrayList();
    		coll.add("AA");
    		coll.add("BB");
    		coll.add(123);
    		coll.add(new Date());
    	
    		//size():获取添加的元素的个数
    		System.out.println(coll.size());
    	
    		//addAll() 将coll1中的元素添加到coll中
    		Collection coll1 = new ArrayList();
    		coll1.add("CC");
    		coll1.add(456);
    	
    		coll.addAll(coll1);
    		System.out.println(coll);
    	
    		// clear() 清空集合元素
    		coll.clear();
    	
    		// isEmpty() 判断当前集合是否为空
    		System.out.println(coll.isEmpty());
    	
    		// contains 当前集合中是否包含xx.调用的是equals
    		// 在判断时会调用OBJ对象所在类的equals方法
    	
    		System.out.println(coll.contains("CC"));
    	
    		// containsAll(Collection coll1) 判断形参coll1中的所有元素是否都在当前集合中
    		Collection coll2 = Arrays.asList(123,456);
    		System.out.println(coll.containsAll(coll2));
    	}
    	@Test
    	public void test2(){
    		Collection coll = new ArrayList();
    		coll.add("AA");
    		coll.add("BB");
    		coll.add(123);
    		coll.add(new Date());
    		//remove 返回的是布尔值,移除了就返回true
    		coll.remove("AA"); //可以用一个boolean的值去接收他
    		System.out.println(coll);
    	
    		// removeAll(Collention coll1) 从当前元素中移出cool1中所有元素
    		Collection coll1 = Arrays.asList(123,4567);
    		coll.removeAll(coll1);
    		System.out.println(coll);
    	
    	}
    	@Test
    	public void test3(){
    		Collection coll = new ArrayList();
    		coll.add("AA");
    		coll.add("BB");
    		coll.add(123);
    		coll.add(new Date());
    	
    //		// 获取当前集合与coll1的交集,并返回给当前集合
    //		Collection coll1 = Arrays.asList(123,456,789);
    //		coll.retainAll(coll1);
    //		System.out.println(coll);
    	
    		// equlas
    		Collection coll2 = new ArrayList();
    		coll2.add("AA");
    		coll2.add("BB");
    		coll2.add(123);
    		coll2.add(new Date());
    	
    		System.out.println(coll.equals(coll2)); //顺序也要一样噢
    	}
    
    	@Test
    	public void test4(){
    		Collection coll = new ArrayList();
    		coll.add("AA");
    		coll.add("BB");
    		coll.add(123);
    		coll.add(new Date());
    	
    		//hashCode() 返回当前对象的哈希值
    		System.out.println(coll.hashCode());
    	
    	
    		// 集合---->数组,toArray()
    		Object[] arr = coll.toArray();
    		for(int i = 0;i < arr.length ; i++){
    			System.out.println(arr[i]);
    	
    		// 扩展:数组-->集合,调用Arrays类的静态方法asList()
    //		List list = Arrays.asList(new String[]{"AA","BB","CC"});
    //		System.out.println(list);
    //		
    		
    		}
    	
    	}
    
    }
    
    • 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
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113

    Iterator 接口遍历集合元素

    在这里插入图片描述

    package Collection;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.Iterator;
    
    import org.junit.Test;
    
    public class IteratorTest {
    	@Test
    	public void test(){
    		Collection coll = new ArrayList();
    		coll.add("AA");
    		coll.add("BB");
    		coll.add(123);
    		coll.add(new Date());
    	
    		Iterator iterator = coll.iterator();
    	
    		//方式一:不推荐
    		for (int i = 0;i < coll.size();i++){
    			System.out.println(iterator.next());
    		}
    		// 方式二:推荐
    		while(iterator.hasNext()){ //还有没有下一个
    			//next指针下移,将下移后的值返回
    			System.out.println(iterator.next());
    		}
    //		// 错误方法,他每调一次while 就有一个新的迭代器
    //		while(coll.iterator().hasNext()){
    //			System.out.println(coll.iterator().next());//死循环
    //		}		
    	
    	}
    	// remove方法,在遍历中删除集合中的元素,不同于集合直接调用remove
    	@Test 
    	public void test2(){
    		Collection coll = new ArrayList();
    		coll.add("AA");
    		coll.add("BB");
    		coll.add(123);
    		coll.add(new Date());
    	
    		Iterator iterator = coll.iterator();
    		while(iterator.hasNext()){
    			Object obj = iterator.next();
    			if("AA".equals(obj)){  
    				iterator.remove(); //删除集合中AA字符串
    			}
    		}
    	
    		iterator = coll.iterator();
    		while(iterator.hasNext()){
    			System.out.println(iterator.next());
    		}
    	}
    }
    
    • 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

    JDK5.0新增了foreach循环,用于遍历集合、数组

    package Collection;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    
    import org.junit.Test;
    
    public class ForTest {
    	@Test
    	public void test(){
    	Collection coll = new ArrayList();
    	coll.add("AA");
    	coll.add("BB");
    	coll.add(123);
    	coll.add(new Date());
    
    	// for(集合中元素类型 局部遍历 : 集合对象)
    	// 内部仍然调用迭代器
    	for (Object obj : coll){
    		System.out.println(obj);
    	}
    	}
    
    	@Test
    	public void test2(){
    		int[] arr = new int[]{1,2,3,4};
    		for(int i : arr){
    			System.out.println(i);
    		}
    	}
    
    	@Test
    	public void test3(){
    		String[] arr = new String[]{"MM","MM","MM"};
    	
    		// 方式一 普通for循环 数组内部都会被改变
    		for(int i = 0;i < arr.length;i++){
    			arr[i] = "GG";
    		}
    	
    		// 方式二:增强for循环,数组内部最后还是不会变,是形参变了
    //		for(String s : arr){
    //			s = "GG";
    //		}
    //		
    		for(String s : arr){
    			System.out.println(s);
    		}
    	}
    }
    
    • 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

    List接口

    在这里插入图片描述

    ArrayList,LinkedList,Vector三者的异同?

    三个类都是List接口,存储数据的特点相同,存储有序的,可重复的数组

    • ArrayList 作为List的主要实现类,线程不安全的,效率高,底层使用Object[] elementData存储
    • LinkedList 底层使用双向链表,对于频繁的插入和删除,使用效率比ArrayList高
    • Vector 作为List的古老实现类,线程安全的,效率低,底层使用Object[] elementData存储

    ArrayList

    jdk7 的情况下
    ArrayList List = new ArrayList(); //底层创建了长度为10的Object[]数组
    List.add(123);//elementData[0] = new Integer(123);
    如果此次的添加导致底层的数组容量不够,则扩容;
    扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中

    建议开发中去使用带参的构造器,ArrayList List = new ArrayList(int capacity)

    jdk8 中 ArrayList的变化
    ArrayList List = new ArrayList();//底层Object[] elementData 初始化为{ },并没有创建长度为10的数组
    List.add(123);才创建长度为10的数组,并将123添加到elementData[0]
    后续添加与扩容操作与jdk7无异

    小结:jdk7中ArrayList对象的创建类似于单例的饿汉式。jdk8中ArrayList对象的创建类似于单例的懒汉式。延迟了数组的创建,节省内存。

    LinkedList

    LinkedList list = new LinkedList;//内部声明了node类型的first 和last
    list.add(123);//将123封装到node中,创建了node对象

    Vector

    底层创建了长度为10的Object[]数组,在扩容方面,扩容为原来的2倍

    List的API

    在这里插入图片描述

    Set接口

    Set ---- 无序的、不可重复的

    • HashSet :作为Set接口的主要实现类,线程不安全的,可以储存null值
    • LinkedSet :作为HashSet的子类,遍历其内部数据时,可以按照添加的数据遍历
    • TreeSet:可以按照添加元素的指定属性进行排序

    无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的Hash值来决定

    不可重复性:保证添加的元素按照equals方法判断时,不能返回true,即相同的元素不能添加进来。

    添加元素的过程(以HashSet为例

    我们向HashSet添加元素a,首先调用元素a的hashcode()方法,计算元素a的哈希值,通过此哈希值算出在HashSet底层存放位置,判断在此位置上是否有其他元素
    如果没有其他元素,则直接放入
    如果此位置上有其他元素b(或以链表形式存放)则比较a和b的哈希值
    如果哈希值不相同,则添加元素a成功
    如果哈希值相同,进而需要调用元素a所在类的equals方法,返回true则添加成功
    对于情况2和情况3而言,元素a与已经存在的的数据以链表的形式存储
    jdk7.0:元素a放到原来的数组中,指向原来的数组
    jdk8.0:原来的元素在数组中,指向元素a

    对于存放在Set容器中的类,必须要重写hashcode和equals

    最好直接Alt + shift + s去生成

    LinkedHashSet 在添加数据的同时,每个数据还维护了两个引用,记录此数据前后的数据

    优点:对于频繁的遍历操作,LinkHashSet效率比HashSet高

    TreeSet

    向TreeSet当中添加的数据,要求是相同类的对象

    两种排序:自然排序、定制排序

    自然排序中,比较两个对象是否相同的标准:compareTo()方法,不再是equals

    定制排序:构造TreeSet时带参数,参数为比较的方法compare()方法

    Map 接口

    Map : 双列数据,存储key - value 对的数据 类似于高中的函数:y = f(x)
    |--------HashMap 作为Map的主要实现类,线程不安全的,效率高。可以存储null的key和value
    --------------------------LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
    原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
    对于频繁的遍历操作,此类执行效率高于HashMap
    |-------- TreeMap:保证按照添加的key - value 进行排序,实现排序遍历。此时考虑key 的自然排序和定制排序。底层使用红黑树
    |--------Hashtable 作为古老的实现类 ,线程安全的,效率低。不能存储null的key和value
    --------------------------Properties:常用来处理配置文件。key 和 value 都是String 类型

    import java.util.HashMap;
    import java.util.Map;
    
    import org.junit.Test;
    
    public class MapTest {
    	@Test
    	public void test(){
    		Map map = new HashMap();
    		map.put(null, null);
    		System.out.println(map);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    HashMap的底层

    数组 + 链表 (jdk7之前)
    数组 + 链表 + 红黑树(jdk8.0)

    Map 结构理解

    map 中的key是无序的、不可重复的,使用Set存储所有的value --> key所在类要重写equals 和 hashCode (以hashMap为例)
    map 中的Value无序的、可重复的,用Collection 存储所有的value —> values 所在类要重写equals
    一个键值对:key - value 构成了一个Entry对象
    Map中的Entry :无序的、不可重复的,使用Set存储所有的Entry

    HashMap 底层实现原理 (以jdk7为例说明

    HashMap map = new HashMap();
    
    • 1

    底层创建了一个长度为16的一个一维数组Enter[] table

    map.put(key1,value1);
    首先,调用key1所在类的hashcode()计算key1哈希值,此哈希值经过某种计算以后,得到在Entry数组中的存放位置,如果在此位置上的数据为空,此时的key1 - value1 添加成功 --情况一
    如果此位置上不为空,(意味着此位置上存在一个或多个数据(以链表形式)),比较key1与他们的哈希值,
    如果key1与他们的哈希值都不相同,则key1 - value1 添加成功 --情况二
    如果key1的哈希值与已经存在的某一个数据相同,则比较key1所在类的equals方法
    如果equals 返回false ,则key1 - value1 添加成功 --情况三
    如果equals 返回ture ,使用value1 去替换相同key的value值

    关于情况二和情况三,此时的key1 - value1 的数据以链表的方式存储
    在不断的添加过程中,会涉及到扩容问题,默认的扩容方式,扩容为原来容量的二倍,并将原有数据复制

    jdk8相对于Jdk7的一些不同

    new HashMap() 的时候,没有创建一个长度为16的数组
    jdk底层的数组是node类型的数组,而非entry数组
    首次调用put()方法时,才创建长度为16的数组
    jdk7.0底层结构只有,数组+链表 jdk8.0底层结构是 数组 + 链表 + 红黑树
    当数组的某一个索引上的元素以链表存在的数据个数大于8,且当前数组长度>64
    此时索引位置上的所有数组改为红黑树存储

    源码

    在这里插入图片描述

    LinkedHashMap(了解就行)

    能够记录添加元素的前后顺序
    对于遍历操作很多的时候,可以考虑使用LinkedHashMap

    Map接口中定义的方法

    在这里插入图片描述

    常用方法:

    添:put
    删:removt
    改:put
    查询:get
    长度:size()
    遍历:keySet / values()/enterSet

    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    import org.junit.Test;
    
    public class MapTest {
    	@Test
    	public void test(){
    		Map map = new HashMap();
    		map.put(null, null);
    		System.out.println(map);
    	}
    
    
    	@Test
    	public void test2(){
    		Map map = new HashMap();
    		map.put("aA",1);
    		map.put("bA",2);
    		map.put("cA",3);
    	
    		// 遍历所有的key
    		Set set = map.keySet();
    		Iterator iterator = set.iterator();
    		while(iterator.hasNext()){
    			System.out.println(iterator.next());
    		}
    	
    		// 遍历所有的values,是Collection 可以直接用它的方法
    		Collection coll = map.values();
    		for(Object obj : coll){
    			System.out.println(obj);
    		}
    	
    		// 遍历所有的key - value
    		Set entrySet = map.entrySet();
    		Iterator iterator2 = entrySet.iterator();
    		while(iterator2.hasNext()){
    //			System.out.println(iterator2.next());
    			Object obj = iterator2.next();
    			Map.Entry entry = (Map.Entry) obj;
    			System.out.println(entry.getKey() + "------>" + entry.getValue());//也能这样
    			System.out.println(obj.);
    		}
    	
    	}
    }
    
    • 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

    向TreeMap中添加key - value ,要求key必须是同一类的对象

    因为key要进行排序,自然排序、定制排序

    Properties

    key - value 都是字符串类型

    package Collection;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.util.Properties;
    
    import org.junit.Test;
    
    public class PropertiesTest {
    	@Test
    	public void test() throws Exception{
    		Properties pro = new Properties();
    		FileInputStream fis = new FileInputStream("jdbc.properties");
    		pro.load(fis); //加载对应流文件
    		String name = pro.getProperty("name");
    		System.out.println(name);
    	
    	
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    jdbc.properties 如下
    在这里插入图片描述

    Collections 工具类

    Collections是操作Collection 和 Map的工具类

    Collections 和 Collection的区别

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

  • 相关阅读:
    .netCore用DispatchProxy实现动态代理
    【ROS2初级知识10】: ROS2的参数(Python)
    Java8新特性
    Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单
    c++暴力法
    如何实现一个业务系统的自动化框架搭建
    纯 CSS 实现搜索框的展示与隐藏
    Cannot use object of type __PHP_Incomplete_Class as array
    2021年上半年软件设计师上午真题及答案解析(二)
    LeetCode第9题:回文数
  • 原文地址:https://blog.csdn.net/abc1234564546/article/details/127897771