Java 集合体系 学习 笔记 (超详细总结,适合新手观看学习)

一、概念

Java集合和数组一样,都是存放一组相同类型数据的容器。Java集合和数组的不同点在于以下几点。

1、虽然Java和数组都是存放一组相同类型的数据,但是数组是任何一种类型都可以存储,集合只能存放引用数据类型的数据(集合底层使用泛型来定义存储的数据类型)。

2、数组有一个长度,长度一旦确定不可改变。Java集合容量没有限制 - 自动扩容的。

【补充】StringBuffer、StringBuilder底层也可以自动扩容:借助Arrays.copyof(),底层又借助了System.arrayCopy()。

二、集合分类 - java.util

在Java当中,提供了各种各样的集合用来满足不同的业务需求。

1、单列集合:一条数据只有一列

所有的单列集合都是Collection接口的子类,Collection封装了很多单列集合共有的方法,只不过这些方法基本上都是抽象方法。

单列集合Collection继承了Iterable,遍历Java集合。可通过迭代器、增强for循环进行遍历。

package com.nuc.kang.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**
* Collection接口给我们提供的单列集合常用的方法
* 	size():int 获取集合存放的元素个数
* 	isEmpty():boolean 判断集合是否为空集合
* 	contains(Object):boolean 判断集合是否包含该元素
* 	iterator():Iterator<E> 获取集合的迭代器,用于遍历集合
* 	toArray():Object[] 将集合转换为数组
* 	toArray(T[]):T[]  将集合转换为指定类型的数组
* 	add(E):boolean  将元素加到集合当中
* 	remove:Object  移除某个元素
* 	clear()  清空集合
* @author 冰霜中的独舞
* @version 2023年7月3日 下午7:27:30
*
*/
public class Demo01 {

	public static void main(String[] args) {
		Collection<Integer> col = new ArrayList<>();
		System.out.println(col.size());
		System.out.println(col.isEmpty());
		col.add(1);
		System.out.println(col.contains(1));
		col.add(2);
		/**
		 * 遍历集合:两种遍历方式
		 * 1、增强的for循环
		 * 2、迭代器也可以遍历  获取迭代器  借助迭代器的hasNext判断有没有下一条数据 然后再借助next获取下一条数据
		 */
		for(Integer ele : col) {
			System.out.println(ele);
		}
		
		Iterator<Integer> iterator = col.iterator();
		while(iterator.hasNext()) {
			Integer next = iterator.next();
			System.out.println(next);
		}
		
		col.remove(2);
		System.out.println(col);
		
		col.clear();
		System.out.println(col);
		
		col.add(1);
		col.add(8);
		Object[] array = col.toArray();
		System.out.println(Arrays.toString(array));
		
		Integer[] array1 = new Integer[col.size()];
		col.toArray(array1);
		System.out.println(Arrays.toString(array1));
	}
}

image-20230703203951071

单列集合又细分为两种,都是Collection接口的一个子接口:

1.1 List集合

  • List接口类型的集合:所有数据可以重复,而且是有序的 - 加入有序

  • 提供几个可以使用索引进行取值赋值的操作

  • List接口的三个实现类:

    • Vector:一般扩容为原先的2倍,如果有扩容因子,那么就是扩容为原先的长度 + 扩容因子
    import java.util.Vector;
    /**
    * List的实现类: list的实现类除了LinkedList增加了几个特殊方法外,
    * Vector和ArrayList基本没在接口之上再增加新的方法。
    * Vector<>():
    * 		无参构造器底层调用this(10),底层先给你创建一个容量为10的数组存放元素,扩容因子也是0
    * Vector(int initialCapacity):
    * 		有参构造器底层调用this(initialCapacity,0):底层给你创建一个指定长度的数组,顺序再指定一个扩容因子为0
    * Vector(int initialCapacity,int capacityIncrement):底层创建一个指定长度的数组,指定数值的扩容因子
    * 
    * Vector底层扩容的时候默认扩容为原先的一倍,但是如果扩容因子不为0的话,那么扩容为就数组长度+扩容因子
    */
    public class ListImpleDemo01 {
    
    	public static void main(String[] args) {
    		Vector<Integer> vec = new Vector<>();
    		vec.add(1);
    		vec.add(1,2);
    		vec.add(3);
    		vec.add(1);
    		System.out.println(vec);
    	}
    }
    
    • ArrayList:一般扩容为原先的1.5

      以上两种是底层借助数组实现,数据可以重复,而且有序 - 加入有序

    import java.util.ArrayList;
    /**
    * ArrayList创建
    * ArrayList():
    * 		底层会创建一个长度为10的数组存放数据,
    * 		但是一定要注意,长度为10的数组并不是在构造器中直接创建的,而是在集合第一次增加元素的时候创建的
    * ArrayList(int capacity)
    * ArrayList(Collection)
    */
    public class ListImpleDemo02 {
    
    	public static void main(String[] args) {
    		ArrayList<Integer> list = new ArrayList<>();
    		list.addAll(new ArrayList<Integer>(20));
    	}
    }
    
    • LinkedList:扩容是通过Node内部类完成

      底层借助双向链表来实现,数据可以重复,而且加入有序

    import java.util.LinkedList;
    /**
    * 
    * LinkedList也是JavaList集合体系的一个实现类,只不过LinkedList底层不是借助数组来存储数据的
    * 而是借助双向链表去存储数据,而且通过双向链表维护数据的加入顺序
    * 
    * LinkedList因为使用双向链表(prev,datasource,next)来存储数据,在类中提前把链表的头部节点和尾部节点已经提前定义出来了
    * 因此LinkedList在Collection、List接口之上提供了四个比较特殊的方法,可以直接对集合的头部节点和尾部节点进行操作
    * 	addFirst(E)--在头部增加数据
    * 	addLast(E)--在尾部增加数据
    * 	add(E)--默认在尾部增加数据
    * 	removeFirst()--移除头部元素
    * 	removeLast()--移除尾部元素
    * 
    * LinkedList一般用在频繁的修改和数据变更下。
    * ArrayList更适合使用在频繁的数据查找下。
    */
    public class ListImpleDemo03 {
    	public static void main(String[] args) {
    		LinkedList<Integer> list = new LinkedList<>();
    		list.add(1);
    		System.out.println(list);
    	}
    }
    
    

1.2 Set集合

  • Set接口类型的集合:数据不允许重复,而且数据不一定有序

  • Set接口的三个实现类:

    • HashSet: 不允许重复,元素是无序
    • LinkedHashSet:不允许重复,但是元素是有序的,加入有序
    • TreeSet:不允许重复,但是元素有序的,大小有序,treeset集合中元素必须有比较器
  • Set判重验证

package com.nuc.kang.collection;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

/**
* Set集合也是一个单例集合,是Collection的子接口
* Set接口集合体系没有提供任何的多余方法,使用的集合增加数据方法都是Collection提供的
* Set接口集合虽然没有提供多余的方法,但是提供了存储数据的特性,元素不能重复
* 
* Set集合去判断两个元素是否重复借助Java的两个方法完成的:
* 	(1)hashCode:返回一个整数类型的值,默认返回的是对象在堆区的地址。
* 	(2)equals方法:比较两个对象是否值相等,默认情况下比较两个对象的地址相等。
* 	【注意】在Java中有要求的,两个对象通过equals返回比较为true的话,那么两个对象的hashCode方法必须返回相同的值
* 		如果两个对象的hashCode值不一样 那么两个对象一定不相等,如果两个对象的hashCode值一样的,不一定相等。
* 	判断规则:
* 		(1)set集合在添加元素时,先通过待添加元素的hashCode值和集合中的每一个元素的hashCode值做比较,如果hashCode值都不一样,那么认为元素不重复,直接添加到集合当中了
* 		(2)如果hashCode值重复了,那么调用equals方法看返回结果,返回结果为true,那么重复 不添加  如果返回结果为false  那么就是不重复 添加
*
*/
public class SetDemo01 {
	public static void main(String[] args) {
		//Set<Integer> set = new HashSet<>();//[1, 19, 7, 8, 10]
		//Set<Integer> set = new LinkedHashSet<>();//[1, 10, 19, 8, 7]
		Set<Integer> set = new TreeSet<>();//[1, 7, 8, 10, 19]
		set.add(1);
		set.add(1);
		set.add(1);
		set.add(10);
		set.add(19);
		set.add(8);
		set.add(7);
		System.out.println(set);
	}
}
package com.nuc.kang.collection;

import java.util.HashSet;
import java.util.Objects;
import java.util.Random;
import java.util.Set;

/**
* set判重验证
*/
public class SetDemo02 {

	public static void main(String[] args) {
		Set<Student> set = new HashSet<>();
		Student stu = new Student("zs", 18, "s001");
		Student stu1 = new Student("zs", 18, "s001");
		set.add(stu);
		set.add(stu1);
		System.out.println(set);
	}
}
class Student {
	private String name;
	private Integer age;
	private String sno;
	public Student(String name, Integer age, String sno) {
		super();
		this.name = name;
		this.age = age;
		this.sno = sno;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", sno=" + sno + "]";
	}
	
	@Override
	public int hashCode() {
		return Objects.hash(age, name, sno);
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		return Objects.equals(age, other.age) && Objects.equals(name, other.name) && Objects.equals(sno, other.sno);
	}
}

image-20230704211348334

  • TreeSet实现大小排序:

    • 实现Comparable接口
    package com.nuc.kang.collection;
    
    import java.util.HashSet;
    import java.util.Objects;
    import java.util.Random;
    import java.util.Set;
    
    class Student implements Comparable<Student>{
    	private String name;
    	private Integer age;
    	private String sno;
    	public Student(String name, Integer age, String sno) {
    		super();
    		this.name = name;
    		this.age = age;
    		this.sno = sno;
    	}
    
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + ", sno=" + sno + "]";
    	}
    	
    	@Override
    	public int hashCode() {
    		return Objects.hash(age, name, sno);
    	}
    	
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Student other = (Student) obj;
    		return Objects.equals(age, other.age) && Objects.equals(name, other.name) && Objects.equals(sno, other.sno);
    	}
    	@Override
    	public int compareTo(Student o) {
    		if(this.age > o.age) {
    			return 1;
    		}else if(this.age < o.age) {
    			return -1;
    		}else {
    			return 0;
    		}
    	}
    }
    
    package com.nuc.kang.collection;
    
    import java.util.Comparator;
    import java.util.Set;
    import java.util.TreeSet;
    
    public class SetDemo03 {
    	public static void main(String[] args) {
    		Set<Student> set = new TreeSet<>();
    		Student stu = new Student("zs", 20, "s001");
    		Student stu1 = new Student("ls", 18, "s002");
    		Student stu2 = new Student("ww", 15, "s003");
    		set.add(stu);
    		set.add(stu1);
    		set.add(stu2);
    		System.out.println(set);
    	}
    }
    
    • 创建Comparator的比较器
    package com.nuc.kang.collection;
    
    import java.util.Objects;
    import java.util.Random;
    import java.util.Set;
    
    class Student {
    	private String name;
    	private Integer age;
    	private String sno;
    	public Student(String name, Integer age, String sno) {
    		super();
    		this.name = name;
    		this.age = age;
    		this.sno = sno;
    	}
    	
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Integer getAge() {
    		return age;
    	}
    
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    
    	public String getSno() {
    		return sno;
    	}
    
    	public void setSno(String sno) {
    		this.sno = sno;
    	}
    
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + ", sno=" + sno + "]";
    	}
    	
    	@Override
    	public int hashCode() {
    		return Objects.hash(age, name, sno);
    	}
    	
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Student other = (Student) obj;
    		return Objects.equals(age, other.age) && Objects.equals(name, other.name) && Objects.equals(sno, other.sno);
    	}
    }
    
    package com.nuc.kang.collection;
    
    import java.util.Comparator;
    import java.util.Set;
    import java.util.TreeSet;
    
    public class SetDemo03 {
    	public static void main(String[] args) {
    		//TreeSet实现元素大小排序,在TreeSet构造器里面传上一个匿名内部类的comparator的比较器
    		Set<Student> set = new TreeSet<>(new Comparator<Student>() {
    			@Override
    			public int compare(Student o1, Student o2) {
    				if(o1.getAge() > o2.getAge()) {
    					return 1;
    				}else if(o1.getAge() < o2.getAge()) {
    					return -1;
    				}else {
    					return 0;
    				}
    			}
    			
    		});
    		Student stu = new Student("zs", 20, "s001");
    		Student stu1 = new Student("ls", 18, "s002");
    		Student stu2 = new Student("ww", 15, "s003");
    		set.add(stu);
    		set.add(stu1);
    		set.add(stu2);
    		System.out.println(set);
    	}
    }
    

    image-20230704211134965

Collections - Java给我们提供的封装了单列集合常用的工具方法的工具类 - 提供的方法针对List集合体系

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Demo01 {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(3,2,1,5,4,6);
		Collections.sort(list);//默认升序
		System.out.println(list);
		//降序
		List<Integer> list3 = Arrays.asList(55,22,44,11,99);
		Collections.sort(list3, new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 > o2 ? -1:(o1 < o2 ? 0:1);
			}
		});
		System.out.println(list3);
		//二分查找
		int i = Collections.binarySearch(list, 1);
		System.out.println(i);
		//构建一个空集合
		List<Object> list2 = Collections.emptyList();
		//数组反转
		Collections.reverse(list);
		System.out.println(list);
		//对集合顺序打乱
		Collections.shuffle(list);
		System.out.println(list);
	}
}

image-20230705205515779

2、双列集合:一条数据有两列

所有的双列集合都是Map接口的子类

2.1 特点

  • 每一行数据都是有两列组成的,其中第一列称为key第二列称为value

  • 其中在Map集合当中,key值不允许重复value允许重复的。Map集合底层所有的key值通过Set集合来进行存储的Value值通过Collection集合进行存储的

  • 如果Map集合增加了重复性的key值,会把原有的key值对应的value数据替换掉

2.2 Map接口的常用方法

image-20230705210539605

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

/**
* Map集合常用方法、map集合的定义方式
*/
public class Demo01 {
	public static void main(String[] args) {
		Map<String,Double> map = new HashMap<>();
		System.out.println(map.size());//查看集合的元素个数
		System.out.println(map.isEmpty());//判断map集合是否为空
		///map集合添加元素
		map.put("香酥鸡", 90.3);
		map.put("糖醋丸子", 18.0);
		map.put("鱼香肉丝", 26.4);
		map.put("鸡公煲", 36.5);
		map.put("香酥鸡", 45.3);
		map.put("北京烤鸭", 76.4);
		System.out.println(map);
		//判断map集合是否包含某个key值
		System.out.println(map.containsKey("鸡公煲"));
		System.out.println(map.containsKey("清蒸鲈鱼"));
		//根据key值获取map集合中对应的value值  如果key值不存在,那么会得到一个null值
		Double price = map.get("鱼香肉丝");
		System.out.println(price);
		//map集合为了预防获取不存在的key值导致空指针问题,提供了一个获取的方法并且防止null值
		Double orDefault = map.getOrDefault("鱼香肉丝", 0.0);
		System.out.println(orDefault);
		//清空集合
//		map.clear();
//		System.out.println(map);
		//map集合元素替换--key对应的value
		map.replace("鱼香肉丝", 158.0);
		System.out.println(map);
		//根据key移除map集合中的某个元素
		Double remove = map.remove("北京烤鸭");
		System.out.println(map);
		/**
		 * Map集合的遍历:
		 * 		keySet():Set<K>	获取map集合中的所有key值,返回的是set集合
		 * 		entrySet():Set<Entry<K,V>>:获取map集合中所有元素,变成一个set集合,只不过map集合每一条的key和value使用内部类Entry封装起来
		 */
		Set<String> set = map.keySet();
		for(String key : set) {
			Double double1 = map.get(key);
			System.out.println(key + "=" + double1);
		}
		
		Set<Entry<String,Double>> entrySet = map.entrySet();
		for(Entry<String, Double> entry : entrySet) {
			System.out.println(entry.getKey() + "=" + entry.getValue());
		}
	}
}

image-20230705214426122

使用Map集合写的一个菜单管理系统:

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

/**
* 程序启动 要求可以实现在控制台对菜单进行增删改查
* 	1、增加菜品	2、修改菜品价格	3、查询单个菜品	4、查询所有菜品	5、删除菜品
*/
public class MenuManager {
	public static void main(String[] args) {
		//定义一个存放菜品的容器
		Map<String, Double> cd = new HashMap<String, Double>();
		Scanner sc = new Scanner(System.in);
		
		a:while(true) {
			System.out.println("||================================控制台=========================================||");
			System.out.println("||========1、增加菜品 2、修改菜品价格 3、查询单个菜品 4、查询所有菜品 5、删除菜品 6、退出系统=========||");
			System.out.println("||================================控制台=========================================||");
			System.out.print("请输入要执行的操作:");
			int num = sc.nextInt();
			switch (num) {
			case 1 :
				System.out.print("请输入一个菜名:");
				String dish = sc.next();
				System.out.print("请输入菜的价格:");
				double price = sc.nextDouble();
				cd.put(dish, price);
				System.out.println("菜品添加成功!");
				break;
			case 2 :
				System.out.print("请输入一个菜名:");
				String dish1 = sc.next();
				if(cd.containsKey(dish1)) {
					System.out.print("请输入要修改菜名的价格:");
					Double price1 = sc.nextDouble();
					cd.replace(dish1, price1);
					System.out.println("菜品价格修改成功!");
				}else {
					System.out.println("您输入的菜品不存在!");
				}
				break;
			case 3 :
				System.out.print("请输入一个菜名:");
				String dish2 = sc.next();
				if(cd.containsKey(dish2)) {
					System.out.println("您要查询的菜品为:" + dish2 + ",价格为:" + cd.get(dish2));
				}else {
					System.out.println("您输入的菜品不存在!");
				}
				break;
			case 4 :
				Set<Entry<String,Double>> entrySet = cd.entrySet();
				for(Entry<String,Double> entry : entrySet) {
					System.out.println("菜品为:" + entry.getKey() + "价格为:" + entry.getValue());
				}
				break;
			case 5 :
				System.out.print("请输入您要删除的菜品:");
				String dish3 = sc.next();
				if (cd.containsKey(dish3)) {
					cd.remove(dish3);
					System.out.println("您输入的菜品已删除!");
				}else {
					System.out.println("您输入的菜品不存在!");
				}
				break;
			case 6:
				System.out.println("您的系统已退出!");
				break a;
			default:
				System.out.println("输入的操作不存在,请重新输入!");
				break;
			}
		}
	}
}

2.3 Map接口的常用实现类

public class Demo02 {
	public static void main(String[] args) {
		Map<String,Double> map = new HashMap<>();
		map.put("香酥鸡", 90.3);
		map.put("糖醋丸子", 18.0);
		map.put("鱼香肉丝", 26.4);
		map.put("鸡公煲", 36.5);
		map.put("香酥鸡", 45.3);
		map.put("北京烤鸭", 76.4);
		System.out.println(map);
	}
}
2.3.1 HashMap:key元素无序

image-20230706104314881

2.3.2 LinkedHashMap:有序,加入有序

image-20230706104356321

2.3.3 Hashtable:无序 Properties (Hashtable的子类):一般是用来读取一些配置文件数据的
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

/**
* Properties是一个map集合,map集合一般不是当作正常的map集合使用
* 而是专门用来加载一个叫做xxx.properties的一个配置文件中的数据为key-value键值对的。
* 每一行数据必须是如下的格式:
* key=value
*/
public class PropertiesStudy {
	public static void main(String[] args) throws FileNotFoundException, IOException {
		/**
		 * key-value均是Object字符串
		 */
		Properties prop = new Properties();
		prop.put("zs", 1);
		System.out.println(prop);
		/**
		 * prop除了map集合有的方法,还多了三个方法:
		 * 	load()
		 * 	setProperty(String key,String value)===put
		 * 	getProperty(String key)===get
		 */
		prop.load(new FileInputStream("D:\\2023PracticalTraining\\software\\workspace\\eclipseworkspace\\java-study-619\\project.properties"));
		System.out.println(prop);
		String value = prop.getProperty("username");
		System.out.println(value);
		prop.setProperty("username","ls");
		System.out.println(prop);
	}
}
username=zhangsan
password=123456

image-20230706142605018

2.3.4 TreeMap:key的大小有序 key值必须都有比较器

image-20230706104601010

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Augenstern K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值