一、什么是集合

  • 集合是Java中的第二个容器(就是在程序内存中用来存放数据的地方),Java的集合是一个可变长度大小的容器(集合就是可变长度的数组,集合的底层是数组)。
  • 数组是用来存储相同数据类型的容器,集合是用来存放任意对象类型的数据的容器。
  • 集合有长度,集合中的数据称为元素,集合分为很多种类。

二、Collection类型的集合

通过collection来了解集合的特点。

1、Collection

java集合 remove方法不改变 java 集合操作_数据

  • Collection集合是单数据的集合,是根类集合。已知子类接口:set、list、vector
    已知子类:Arraylist、hashset、treeset、linkedList
  • collection集合不能直接确定是有序集合还是无序集合,要根据具体的实例化方式来确定是有序的还是无序的。
    1、1方法
    以Arraylist为子类对象进行操作。
  • ArrayList的默认初始容量为10;
  • 存储的数据类型是基本数据类型的时候会进行自动装箱操作
package com.xingyun.collection;
import java.util.ArrayList;
import java.util.Collection;

/**
 * 根据collection接口来了解集合的基本使用
 * @author langlang
 *
 * 2020年11月25日下午5:13:47
 */
public class CollectionClass {
	
	public static void main(String[] args) {
		
		//创建集合,使用多态的思想,不要忘记导包操作
		Collection   coll = new  ArrayList();
		//添加数据,同一个集合中可以存放任意对象类型的数据
		coll.add(10);//源码进行了自动装箱
		coll.add(20);
		coll.add(true);
		
		//查看数据元素的个数
		System.out.println("元素个数"+coll.size());//元素个数3
	}
}
  • Collection集合,其实使用的是arraylist类的方法。
@Test
	void test1() {
		// 创建集合,使用多态的思想,不要忘记导包操作
		Collection coll = new ArrayList();
		// 添加数据,同一个集合中可以存放任意对象类型的数据
		coll.add(10);// 源码进行了自动装箱
		coll.add(20);
		coll.add(true);

		// 查看数据元素的个数
		System.out.println("元素个数" + coll.size());// 元素个数3

		// 指定查找,有该元素返回true,没有该元素返回false
		System.out.println("指定查找" + coll.contains(10));// 指定查找true

		/*
		 * 使用迭代器查找,Iterator根据集合创建迭代器,进行数据的遍历,注意普通迭代器来说 只能进行集合数据的查看和删除操作
		 * ListItertor属于list独有的
		 */
		Iterator iterator = coll.iterator();
		while (iterator.hasNext()) {
			Object next = iterator.next();
			System.out.print(next);// 1020true
		}

		// 判断是空集合吗
		System.out.println("集合是空的吗" + coll.isEmpty());// 集合是空的吗false

		// 删除集合元素
		System.out.println(coll.remove(10));// true
		System.out.println("元素个数" + coll.size());// 元素个数2
	}
  • 在遍历集合的时候,可以使用Iterator迭代器和foreach循环(有顺序的集合可以使用普通for循环)
// 将集合转为数组
	@Test
	void test3() {

		// 创建集合,使用多态的思想,不要忘记导包操作
		Collection coll = new ArrayList();
		coll.add(10);
		coll.add(20);
		coll.add(true);

		Object[] array = coll.toArray();
		for (Object object : array) {
			System.out.println(object);
		}

	}
  • 集合中的所有数据都可以是不同类型的,使用泛型<>可以约束集合中存放的数据类型。
/*
	 * 集合中存放的数据是任意对象类型的 如何约束集合中所存放的数据,使用泛型 使用泛型就可以指定集合中只能存放的数据类型是什么
	 * 使用泛型后,就不需要强转,迭代器就知道要什么类型
	 */
	@Test
	void test4() {

		// 创建集合,使用多态的思想,不要忘记导包操作
		Collection<String> coll = new ArrayList<String>();
		coll.add("好想爱这个世界啊");
		coll.add("微光");
		coll.add("疯人院");

		// 使用泛型方便进行类型转换
		for (String string : coll) {
			System.out.println(string);
		}

	}
  • 不能对正在使用的集合进行删除元素的操作
// 不能在遍历中对集合元素进行删除操作
	/*
	 * 会产生并发异常,如下所示 ConcurrentModificationException
	 */
	@Test
	void test2() {

		// 创建集合,使用多态的思想,不要忘记导包操作
		Collection coll = new ArrayList();
		coll.add(10);
		coll.add(20);
		coll.add(true);

		// 查询,集合的底层是数组,使用的是foreach
		for (Object object : coll) {
			System.out.println(object);
			// 删除
			coll.remove(10);
		}
	}
  • 将集合可以转为数组使用
  • 集合中可以存放复杂数据类型的操作
/*
	 * 集合中存放的数据是任意对象类型的 如何约束集合中所存放的数据,使用泛型 使用泛型就可以指定集合中只能存放的数据类型是什么
	 * 使用泛型后,就不需要强转,迭代器就知道要什么类型
	 */
	@Test
	void test4() {

		// 创建集合,使用多态的思想,不要忘记导包操作
		Collection<String> coll = new ArrayList<String>();
		coll.add("好想爱这个世界啊");
		coll.add("微光");
		coll.add("疯人院");

		// 使用泛型方便进行类型转换
		for (String string : coll) {
			System.out.println(string);
		}

	}

	/*
	 * 集合中存储复杂数据类型的操作 对象类型 自定义对象 数组类型 元素是数组 集合类型 元素是集合
	 */
	@Test
	void test5() {

		// 创建集合,使用多态的思想,不要忘记导包操作
		Collection<Student> stus = new ArrayList<Student>();
		stus.add(new Student(10, "zs"));
		stus.add(new Student(20, "ww"));
		stus.add(new Student(19, "ls"));

		// 遍历
		for (Student student : stus) {
			System.out.println(student);
		}
	}

	// 数组类型的集合
	@Test
	void test6() {
		Collection<Student[]> stus = new ArrayList<Student[]>();
		stus.add(new Student[] { new Student(10, "zs"), new Student(20, "zs"), new Student(30, "zs") });
		Iterator<Student[]> iterator = stus.iterator();
		while (iterator.hasNext()) {
			Student[] next = iterator.next();
			for (Student student : next) {
				System.out.println(student);
			}
		}

	}

2、List

java集合 remove方法不改变 java 集合操作_System_02

  • List集合为有序可以重复的集合,元素是有顺序的,并且元素可以重复
  • 三个子类的对比
    ArrayList:列表集合,线程不安全,查询速度块,更新速度慢
    LinkedList:链表集合,线程不安全,查询速度慢,更新速度相对较快
    Vector:列表集合,线程安全,查询速度块,更新速度慢,使用的enum做迭代器进行操作
  • 列表和链表的区别
    列表:有顺序,每一个元素都对应一个下标记
    链表:在内存中给每一个元素设置一个尾节点,首尾对象连接。

2、1ArrayList 默认初始容量大小为10

java集合 remove方法不改变 java 集合操作_System_03

  • ArrayList,他的底层是数组,集合中的数据都存放在集合的object数组中;Object [ ] elementData;因此数据在集合中是有顺序的,元素可以重复,每一个元素都对应于一个下标。
@Test
	void  list01(){
		//实例化,泛型不能是基本类型
		List<Integer>  ls = new ArrayList<Integer>();
		//添加数据,下标0---size-1
		ls.add(100);
		ls.add(200);
		ls.add(200);
		System.out.println(ls.size());//3
		
		//给指定位置新增,对原数组中的元素进行位置调整,将新元素插入到该数组
		ls.add(3, 300);
		//使用的是AbstractCollection的toString方法
		System.out.println(ls);//[100, 200, 200, 300]
		System.out.println(ls.size());//4
		
		//修改,修改哪一个元素,修改为什么
		ls.set(3, 200);
		System.out.println(ls);//[100, 200, 200, 200]
		
		//查询  get
		System.out.println(ls.contains(100));//true
        Integer integer = ls.get(0);
        System.out.println(integer);//100		
		
	}
  • 遍历集合
//使用迭代器进行集合操作
	@Test
	void  list02(){
		List<Integer>  ls = new ArrayList<Integer>();
		ls.add(100);
		ls.add(200);
		ls.add(300);
		
//		/*
//		 * 删除元素这块有一个混淆点
//		 */
//		ls.remove(100);//这样表示删除的是100位置的元素
//		ls.remove(new Integer(100));//这样表示删除的是100这个元素
		
		
		//遍历集合
		//增强性for循环
		for (Integer integer : ls) {
			System.out.println(integer);
		}
		
		System.out.println("--------");
		
		
		//使用普通的迭代器,只能对集合进行删除操作
		Iterator<Integer>  iterator = ls.iterator();
		int index = 0;
		//判断有没有下一个元素,指针不动,指针起始位置是第一个元素之前
		while(iterator.hasNext()) {
			//指针移动到有效元素位置上去
			Integer next = iterator.next();
			index++;
			System.out.println(next);
			if(index==1) {
				iterator.remove();
			}
		}
		
		System.out.println("--------");
		
		
		//使用list独有的迭代器
		ListIterator<Integer> listIterator = ls.listIterator();
		while(listIterator.hasNext()) {
			Integer next = listIterator.next();
			System.out.println(next);
			listIterator.set(400);//这样将会把所有的值都设置为400
			//依然不可以使用添加功能
		}
		
		System.out.println("--------");
		
		//使用普通的for循环
		for (int i = 0; i < ls.size(); i++) {
			System.out.println(ls.get(i));
		}
	}

结果如下:

java集合 remove方法不改变 java 集合操作_Test_04

2、2LinkedList

  • LinkedList用来做快速更新集合数据
    方法如下:
  • addFirst( E o );
  • java集合 remove方法不改变 java 集合操作_数据_05

  • addLast( E o );
  • java集合 remove方法不改变 java 集合操作_Test_06

  • getFirst( );
  • java集合 remove方法不改变 java 集合操作_Test_07

  • getLast( );
  • java集合 remove方法不改变 java 集合操作_数据_08

  • peek( );
  • java集合 remove方法不改变 java 集合操作_数据_09

  • poll( );
  • java集合 remove方法不改变 java 集合操作_Test_10

  • remove ( );
  • java集合 remove方法不改变 java 集合操作_java集合 remove方法不改变_11

  • removeFirst( );
  • java集合 remove方法不改变 java 集合操作_System_12

  • removeLast( );
  • java集合 remove方法不改变 java 集合操作_Test_13

  • element( );
  • java集合 remove方法不改变 java 集合操作_数据_14

代码演示如下:

@Test
	void  link() {
		//面向接口编程
		List<String> ll = new  LinkedList<String>();
		LinkedList<String> lls = new  LinkedList<String>();
		//每一次都在末尾新增
		ll.add("100");
		ll.add("200");
		ll.add("300");
		ll.add(1,"400");
		System.out.println(ll);//[100, 400, 200, 300]
		
		lls.add("zs");
		lls.add("ls");
		lls.add("ww");
		System.out.println(lls);//[zs, ls, ww]
		
		//查看
		System.out.println(ll.get(0));
		System.out.println(lls.get(0));
		System.out.println("第一个元素"+lls.getFirst());//第一个元素zs
		System.out.println("最后一个元素"+lls.getLast());//最后一个元素ww
		
		
		
		//遍历集合
		for (String string : lls) {
			System.out.println(string);
		}
		
		System.out.println("--------");
		
		
		//使用迭代器进行遍历
		Iterator<String> iterator = lls.iterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
}

2、3Vector 数组

1、介绍

java集合 remove方法不改变 java 集合操作_Test_15

  • Vector,可变长度的数组,默认初始容量大小是10
  • 可以手动进行设置初始容量的大小。
  • 在自定义的时候,要选取合适的扩容方式
  • new Vector(2);默认扩容机制是之前容量的2倍扩容
  • java集合 remove方法不改变 java 集合操作_java集合 remove方法不改变_16

  • new Vector(2,20);参数一是设置的初始容量,参数二是扩容机制。
  • java集合 remove方法不改变 java 集合操作_Test_17

2、方法

  • addElement(E obj);
  • capacity( );
  • copyInto(Object [] anArray);
  • elements( );

    代码演示如下:
//Vector的扩容机制
	@Test
	void  vt01() {
		//实例化Vector,扩容因子1(扩容的时机),扩容机制为2倍
		//初始容量为2
		Vector<Integer> nums = new Vector<Integer>(2);
		System.out.println("容量大小"+nums.capacity());//容量大小2
		
		nums.add(100);
		nums.add(200);
		nums.add(300);
		nums.add(400);
		
		System.out.println(nums.size());//4
		//当内容的长度变成和容量的大小一样长时,便进行扩容,扩大为原来的2倍
		System.out.println("容量大小"+nums.capacity());//容量大小4
	}
	
	
	
	
	//集合的遍历
	@Test
	void  vt02() {
		//实例化集合
		Vector<Integer>  nums = new  Vector<Integer>();
		nums.add(100);
		nums.add(200);
		nums.add(300);
		
		//遍历
		//使用增强性的for循环对集合进行遍历
		for (Integer integer : nums) {
			System.out.println(integer);
		}
		
		System.out.println("----------");
		
		//使用迭代器对集合进行遍历
		Iterator<Integer>  iterator = nums.iterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		
		
		System.out.println("----------");
		
		
		//使用Vector自己的,获取所有的元素保存到Enumeration集合中
		Enumeration<Integer>   elements = nums.elements();
		while(elements.hasMoreElements()) {
			Integer nextElement = elements.nextElement();
			System.out.println(nextElement);
		}		
	}

3、Set集合,无序不可重复的集合

java集合 remove方法不改变 java 集合操作_java集合 remove方法不改变_18

3、1TreeSet

3、1、1.介绍

  • 此类实现Set接口,该接口由TreeMap实例支持。此类保证排序后的set按照升序排列元素,根据使用的构造方法不同,可能会按照元素的自然顺序进行排序,或者按照在创建set时所提供的比较器进行排序。
  • Treeset是set的已知实现子类,默认按照自然排序。
  • 该集合存和取的顺序不一样
  • 底层存储数据的时候,是按照排序方式进行存储的
    数字:按大小顺序进行存储
    字母:按字母顺序进行存储
    汉字:按hashcode值进行存储
  • 我们也可以使用自定义的比较器:根据自定义比较器的返回值决定元素是否进行交换。
    代码演示如下:
/**
	 * 自然顺序
	 * 数字:按照数字的大小
	 * 汉字:按照hashcode的值
	 * 英语:26个字母
	 */
	
	@Test
	void  set01() {
		//实例化
		Set<Integer>  snum = new TreeSet<Integer>();
		//存数据的时候要先进行判断原集合中有没有该元素,
		/*
		 * add方法的返回值是一个boolean类型的,
		 * 如果集合中不存在我们要存入的元素,则会存储成功
		 * 如果存储成功则返回true,否则返回false
		 */
		snum.add(10);
		snum.add(20);
		System.out.println(snum.add(30));//true
		System.out.println(snum.add(30));//false
		
		
		System.out.println("------------");
		
		
		//遍历集合
		//使用增强型for循环进行遍历
		for (Integer integer : snum) {
			System.out.println(integer);
		}
		
		
		System.out.println("------------");
		
		
		//使用迭代器进行遍历
		Iterator<Integer>  iterator = snum.iterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		
		
		System.out.println("------------");
		
		
		//该方法是1.8之后才有的
		Spliterator<Integer> spliterator = snum.spliterator();
		System.out.println(spliterator.characteristics());
	}
	
	
	@Test
	void  set02() {
		//实例化
		Set<String>  snum = new TreeSet<String>();
		
		//存数据的时候他会先进行判断
		snum.add("a");
		snum.add("b");
		snum.add("c");
		snum.add("d");
		
		String  a = "啊";
		String  a1 = "和";
		String  a2 = "打";
		System.out.println(a.hashCode());//21834
		System.out.println(a1.hashCode());//21644
		System.out.println(a2.hashCode());//25171
		
		snum.add(a);
		snum.add(a1);
		snum.add(a2);
		
		System.out.println(snum);//[a, b, c, d, 和, 啊, 打]
	}
	
	
	
	//自定义排序规则
	@Test
	void  set03() {
		//实例化,传入比较器
		Set<Integer> snum = new TreeSet<Integer>(new MyComparator());
		snum.add(10);
		snum.add(20);
		snum.add(15);
		snum.add(30);
		
		System.out.println(snum);//[30, 20, 15, 10]
		
	}
package com.xingyun.set;
import java.util.Comparator;
/**
 * 自定义的逆序排列比较器
 * @author langlang
 *
 * 2020年11月26日下午3:11:30
 */
public class MyComparator  implements  Comparator<Integer>{
	//逆序排列
	@Override
	public int compare(Integer num1, Integer num2) {
		//返回值,决定两个元素是否交换
		if(num1>num2) {
			return  -1;//-1代表不交换
		}else if(num1<num2) {
			return  1;//1代表交换
		}else {
			return 0;
		}}
}

3、1、2注意事项:
TreeSet存储对象类型的时候,因为他是自然排序,对于对象来说,不能够直接进行比较,否则会抛出ClassCastException异常。处理方式见代码。

//使用Treeset保存学生对象
	@Test
	void colls4() {
		TreeSet<Student>  stus = new TreeSet<Student>(new  MyComparator());
		/*
		 * 不能直接比较,默认的是自然排序
		 */
		
		//方式一
		/*
		 * 自定义比较器来进行比较,
		 */
		stus.add(new Student(30));
		stus.add(new Student(20));
		stus.add(new Student(15));
		stus.add(new Student(50));
		stus.add(new Student(18));
		System.out.println(stus);
	}
}

class  MyComparator implements Comparator<Student> {

	@Override
	public int compare(Student o1, Student o2) {
		// 两个对象去比较,实际是按照学生的年龄进行比较
		if (o1.age > o2.age) {
			return 1;// 1代表交换顺序
		} else if (o1.age < o2.age) {
			return -1;
		} else {
			return 0;
		}
	}

3、2HashSet

3、1介绍

java集合 remove方法不改变 java 集合操作_Test_19

  • Hashset的底层是hashmap,根据hash码进行排序。可以存放null值,null只能有一个
  • HashSet的默认初始容量是16。
    3、2方法
    构造方法:
    由构造方法可得:HashSet的初始容量大小为16,加载因子为0.75;
    方法:

4、Collections

4、1介绍

java集合 remove方法不改变 java 集合操作_java集合 remove方法不改变_20

  • Collections是collection类型集合的操作类
    4、2方法
  • addAll(Collection<? super T> c, T… a)
  • unmodifiableSet(Set<? extends T> s);
    获得一个不可变的集合;
  • replaceAll(List list, T oldVal, T newVal) ;
  • reverse(List<?> list);
  • sort(List list) ;
  • sort(List list, Comparator<? super T> c) ;
  • 通过不安全集合,得到一个线程安全的集合
    synchronizedCollection(Collection c);
  • 获取集合中的最大值和最小值(比较器)
    max(Collection<? extends T> coll);

    min(Collection<? extends T> coll);

    4、3方法的代码演示如下:
package com.xingyun.collections;

import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.jupiter.api.Test;

/**
 * Collections集合的操作
 * 
 * @author langlang
 *
 *         2020年11月28日下午3:10:16
 */
class CollectionsClass {

	@Test
	void colls1() {
		// 如何快速得到一个固定大小的集合
		List<Integer> list = Arrays.asList(10, 20, 30);
		list.set(1, 100);
		System.out.println(list);//[10, 100, 30]

		// 通过集合得到一个不可变的集合
		Collection<Integer> coll = Collections.unmodifiableCollection(list);
//		coll.add(100);//这样子会报错,因为他已经是一个不可变的集合了,不能对他再进行增加操作
		System.out.println(coll);//[10, 100, 30]
		// 给指定的集合添加元素
		ArrayList<Integer> nums = new ArrayList<Integer>();
		Collections.addAll(nums, 100, 200, 300);
		System.out.println(nums);//[100, 200, 300]
		// 替换
		boolean replaceAll = Collections.replaceAll(nums, 100, 1000);
		System.out.println("是否替换成功" + replaceAll);//是否替换成功true
		System.out.println("替换后的集合" + nums);//替换后的集合[1000, 200, 300]
	}

	
	
	// 使用集合进行排序
	@Test
	void colls2() {
		// list集合,元素的student对象
		ArrayList<Student> stus = new ArrayList<Student>();
		stus.add(new Student(30));
		stus.add(new Student(20));
		stus.add(new Student(15));
		stus.add(new Student(50));
		stus.add(new Student(18));

		// 进行排序
//		// 方式一
//		Collections.sort(stus, new MyComparator());
//		for (Student student : stus) {
//			System.out.println(student);
//		}

		// 方式二 对集合中的对象,实现comparable接口并重写compare To
		Collections.sort(stus);
		for (Student student : stus) {
			System.out.println(student);
		}

	}
	
	
	@Test
	void colls3() {
	   //其他方法	
	   ArrayList<Integer>  nums = new ArrayList<Integer>();
	   Collections.addAll(nums, 100,200,300);
	   ArrayList<Integer>  nums01 = new ArrayList<Integer>();
	   Collections.addAll(nums01, 100,200,300);
	   //交换  swap(List<?> list, int i, int j) 
	   Collections.swap(nums, 0, 2);
	   System.out.println(nums);//[300, 200, 100]
	   //set方法会返回北替换的值
	   System.out.println(nums.set(0, 500));//300
	   System.out.println(nums);//[500, 200, 100]
	   
	   //比较   如果两个指定 collection 中没有相同的元素,则返回 true。
	   boolean disjoint = Collections.disjoint(nums, nums01);
	   System.out.println(disjoint);//false
	}
}

class  MyComparator implements Comparator<Student> {

	@Override
	public int compare(Student o1, Student o2) {
		// 两个对象去比较,实际是按照学生的年龄进行比较
		if (o1.age > o2.age) {
			return 1;// 1代表交换顺序
		} else if (o1.age < o2.age) {
			return -1;
		} else {
			return 0;
		}
	}

}

class Student implements Comparable<Student> {

	int age;

	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Student(int age) {
		super();
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [age=" + age + "]";
	}

	@Override
	public int compareTo(Student stu) {
		// 两个对象去比较,实际是按照学生的年龄进行比较
		if (this.age > stu.age) {
			return 1;// 1代表交换顺序
		} else if (this.age < stu.age) {
			return -1;
		} else {
			return 0;
		}
	}

}

三、Map集合

Map类型的集合称为键值对集合;

java集合 remove方法不改变 java 集合操作_System_21


a.HashMap:线程不安全,按照hash码的值进行排序并允许使用null值和null键,HashMap的执行速度高于TreeMap

b.TreeMap:键不可以为null,值可以为null,根据键的值使用自然排序的方式升序排序,可以使用Comparator进行手动设置排序方式。

c.HashTable:线程安全的,键和值都不能为null.

1、HashMap(hashset)

1.1介绍

java集合 remove方法不改变 java 集合操作_Test_22

  • 允许使用null值和null键
  • HashMap,初始容量为16,加载因子0.75,扩容倍数是两倍
    1、2方法
  • put(K key, V value);
  • remove(Object key);
package com.xingyun.map;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.jupiter.api.Test;
/**
 * HashMap键值对集合
 * @author langlang
 *
 * 2020年11月28日下午4:33:46
 */
public class HashMapClass {	
	
	
	@Test
	void  test01(){                     
		//实例化map集合
		HashMap<String,Integer>  stus = new HashMap<String,Integer>();
		//键不能重复,可以为null
		//值可以重复,可以为null
		stus.put("001",100);
		stus.put("002",200);
		//put方法也可以叫做更新方法
		/*
		 * 如果该键已经存在,那么便更新该键
		 * 如果该键不存在,便添加该键
		 */
//		stus.put("001",300);
		stus.put(null,null);
		stus.put("003",300);

		
//		System.out.println("删除前"+stus);
//		//删除
//		Integer remove = stus.remove("001");
//		//该值返回的是删除的元素的值
//		System.out.println(remove);
		
		
		//查询  遍历key    遍历value   整体遍历
		//将map集合中的所有的value值保存到一个collection集合中
		Collection<Integer> values = stus.values();
		for (Integer integer : values) {
			System.out.println("值为"+integer);
		}
		//遍历所有的key
		Set<String> keySet = stus.keySet();
		for (String string : keySet) {
			System.out.println("键为"+string);
		}
		
		
		//使用enteySet对集合进行遍历,将map集合的键值对关系保存为entry存放到set集合中
		Set<Entry<String, Integer>> entrySet = stus.entrySet();
		for (Entry<String, Integer> entry : entrySet) {
			System.out.println("键是"+entry.getKey()+",值是"+entry.getValue());
		}
		
		
		//判断
		System.out.println(stus.equals(200));
		//集合的长度
		//集合的长度指的是键值对的个数
		System.out.println("集合的长度是"+stus.size());
		
		//映射
		//如果此映射包含对于指定的键的映射关系,则返回 true。
		System.out.println(stus.containsKey("001"));//true
		System.out.println(stus.containsKey("004"));//false
		System.out.println(stus.containsValue(null));//true
	}
	
	
	
	//HashMap存储对象类型
	@Test
	void  test02(){     
		//实例化Map集合
		HashMap<String,Student>  stus = new HashMap<String,Student>();
		//要注意null对象
		stus.put("2101", new Student("zs"));
		stus.put("2102", new Student("zs01"));
		stus.put("2103", new Student("zs02"));
		stus.put("2103", new Student(null));
		
		System.out.println(stus);
		//因为HashMap中允许有null值和null键,因此我们要注意null值的获取
		Collection<Student> values = stus.values();
		for (Student student : values) {
			//注意这里要做非空判断
			if(student!=null) {
				System.out.println(student.name);
			}
		}

	}
}



class  Student{
	
	String  name;

	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Student(String name) {
		super();
		this.name = name;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + "]";
	}
}

2、Hashtable

2、1介绍

java集合 remove方法不改变 java 集合操作_System_23

  • Hashtable的初始默认容量是11,加载因子0.75,扩容机制2倍加1
  • 键和值都不能为null,键和值可以是任意对象类型(自定义对象)
  • 为了成功的在哈希表中存储和检索对象,用做键的对象必须实现hashCode方法和equals方法
    2、2方法
    构造方法

    方法使用以及底层容量获取(反射机制)
package com.xingyun.map;

import java.lang.reflect.Field;
import java.util.Hashtable;
import java.util.Map.Entry;

import org.junit.jupiter.api.Test;

/**
 * Hashtable
 * @author langlang
 *
 * 2020年12月1日下午6:59:11
 */
public class HashtableClass {
	
	
	//hashtable键是基本类型(封装类)
	@Test
	void  hashtable01() {
		//实例化,默认的加载因子是0.75
		//我们设置初始容量为10
		Hashtable<Integer,String>  nums = new Hashtable<Integer,String>(10);
		//循环保存数据
		for (int i = 0; i < 20; i++) {
			nums.put(i,i+"");
		}
		
		/*首先扩容第一次:10*2+1=21;21*0.75<20,因此继续扩容
		 *  再扩容第二次:21*2+1=43;43*0.75>20,因此容量为43
		 */
		
		//打印数据
		System.out.println(nums);
		getCp(nums);//集合的容量43
	}
	
	
	//键是对象类型
	//如果hashtable的键是对象,该对象重写实现hashCode方法和equals方法
	@Test
	void  hashtable02() {
		Hashtable<Person,String>  persons = new Hashtable<Person,String>();
		//如果重写hashcode方法,会导致对象为同一个,key重复了
		persons.put(new Person(20), "中国人");
		persons.put(new Person(20), "外国人");
		/*
		 * 这样键为同一个,put方法的第二个会将第一个的结果进行覆盖
		 */
		System.out.println(persons);//{com.xingyun.map.Person@62d=外国人}
		
		System.out.println("大小是"+persons.size());
		System.out.println(persons.toString());
		//注意:不可以存放null值,会报空指针异常
	//	persons.put(null, null);
	}
	
	
	
	public void getCp(Hashtable<Integer,String> map) {
		 Class c = map.getClass();
		 try {
			Field declaredField = c.getDeclaredField("table");
			//获取权限
			declaredField.setAccessible(true);
			Entry[] entry = (Entry[])declaredField.get(map);
			System.out.println("集合的容量"+entry.length);
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}


class  Person{
	
	String  name;
	int  age;
	
	public Person(String name) {
		super();
		this.name = name;
	}

	public Person(int age) {
		super();
		this.age = age;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	
}

3、TreeMap(treeset) 自然排序

3、1介绍

java集合 remove方法不改变 java 集合操作_Test_24

  • TreeMap是根据键进行自然排序排序的键值对集合,可以使用自定义比较器来改变比较规则
  • TreeMap键不可以为null,值可以是null
package com.xingyun.map;
import java.util.Comparator;
import java.util.TreeMap;
import org.junit.jupiter.api.Test;
/**
 * TreeMap集合
 * 自然排序集合
 * @author langlang
 *
 * 2020年12月1日下午8:03:51
 */
public class TreeMapClass {
	
	/*
	 * comparable是一个函数式接口
	 */
	@Test
	void  treemap01() {
		//key可以为null,value不能为null
		TreeMap<Integer,String>  nums = new  TreeMap<Integer,String>(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				if(o1 > o2) {
					return -1;
				}else  if(o1 < o2) {
					return 1;
				}else {
					return  0;
				}
			}
		}
		);
		nums.put(10, "aa");
		nums.put(5, "aa");
		nums.put(3, "aa");
		nums.put(15, "aa");
		System.out.println(nums);//{15=aa, 10=aa, 5=aa, 3=aa}
	}
	
	
	@Test
	void  treemap02() {
		//使用自定义的比较器
		TreeMap<Integer,String>  nums = new TreeMap<Integer,String>(new ascMyComparator());
		nums.put(10, "aa");
		nums.put(5, "aa");
		nums.put(3, "aa");
		nums.put(15, "aa");
		nums.put(18, "aa");
		System.out.println(nums);//{18=aa, 15=aa, 10=aa, 5=aa, 3=aa}
	}

}

//自定义的正序比较器
class  ascMyComparator   implements  Comparator<Integer>{

	@Override
	public int compare(Integer o1, Integer o2) {
		if(o1>o2) {
			return -1;//1代表交换
		}else if(o1<o2) {
			return 1;
		}else {
			return  0;
		}
	}
}

四、其他集合。

1、Queue

队列集合,先进先出。FIIFO。Queue队列集合使用的是LinkedList操作。

方法如下:

java集合 remove方法不改变 java 集合操作_java集合 remove方法不改变_25


代码演示如下:

@Test
	void  queue(){
		Queue<String>  strs = new LinkedList<String>();
		strs.add("aaa");
		strs.add("bbb");
		strs.add("ccc");
		strs.add("ddd");
		
		System.out.println(strs);
		//使用for循环进行遍历
		for (String string : strs) {
			System.out.println(string);
		}
		
		System.out.println("--------");
		
		//queue自己的方法
		//查找第一个元素
		System.out.println(strs.peek());//aaa
		//移除第一个元素,并得到第一个元素
		System.out.println(strs.poll());//aaa
		System.out.println(strs);//[bbb, ccc, ddd]
		//得到第一个元素
		System.out.println(strs.element());//bbb
		System.out.println(strs);//[bbb, ccc, ddd]
	}

2、Properties

2、1介绍

java集合 remove方法不改变 java 集合操作_Test_26

  • Properties是键值对集合,该集合可以使用io流的操作与properties类型的文件进行数据交互
  • properties文件就是指以properties后缀结尾的文件
  • 该文件中的数据全是字符串的,并且是键值对形式的
  • 该文件在日常的使用中大多数用来保存账号密码,保存的是不重复的数据信息
  • 在eclipse中可以直接创建properties文件,该文件必须保存到项目的根目录下(此时不允许将文件保存到src下,src是资源文件夹)
    2、1方法及代码演示如下
// 将外部文件的内容保存到properties对象中
	@Test
	void properties01() {
		// 实例化properties对象
		Properties pt = new Properties();
//		//存储数据
//		pt.put("aa", 100);//hashtable的方法,不要使用
//		pt.setProperty("bb","200");
//		pt.setProperty("bb01","300");
//		pt.setProperty("bb02","400");
//		System.out.println(pt);//{bb02=400, aa=100, bb01=300, bb=200}
//		//通过键来获取值
//		System.out.println(pt.get("bb"));//200

		// 记载,外部文件,将外部文件的内容保存到properties对象中,使用load方法
		// 参数是InputStream字节输入流
		FileInputStream inputstream;
		try {
			inputstream = new FileInputStream(new File("user.properties"));
			// 读取文件内容
			pt.load(inputstream);
			System.out.println(pt);// {password=123456, username=zs}

			// 修改数据,此时修改的是properties内存中的数据
			pt.setProperty("username", "zhangsan");
			System.out.println(pt);// {password=123456, username=zhangsan}

			// 将内存中对象中的数据,持久化保存到properties文件中
			FileOutputStream outputstrem = new FileOutputStream(new File("user.properties"));
			// 第二个参数就是起一个注释的作用
			pt.store(outputstrem, "修改后的账号信息");
			System.out.println("数据持久化成功");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// 读取数据
	@Test
	void properties02() {
		Properties pt = new Properties();
		FileInputStream inputstream;
		try {
			inputstream = new FileInputStream(new File("user.properties"));
			pt.load(inputstream);
			System.out.println(pt);// {password=123456, username=zhangsan}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	
	// 读取数据
	@Test
	void  properties03(){
		Properties  pt = new Properties();
		pt.setProperty("name","lisi");
		pt.setProperty("pass", "11111");
		
		//将内存中对象中的数据持久化保存到properties文件中
		try {
			FileOutputStream  outputstrem = new FileOutputStream(new File("user.properties"));
			pt.store(outputstrem, "修改后的账号信息");
			System.out.println("数据持久化保存成功");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}