集合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<String> list = Arrays.asList(new String[]{"AA","BB","CC"});
//		System.out.println(list);
//		
		
		}
	
	}

}

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());
		}
	}
}

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);
		}
	}
}

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);
	}
}

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();

底层创建了一个长度为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.);
		}
	
	}
}

向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);
	
	
	}
}

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

Collections 工具类

Collections是操作Collection 和 Map的工具类

Collections 和 Collection的区别

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

猜你喜欢

转载自blog.csdn.net/abc1234564546/article/details/127897771