Collection、Map集合

集合

  • 集合像一个容器,可以一次性容纳其他类型的多个数据,集合在JDK当中java.util包下。
    • 在实际开发中,假设连接数据库,查询出数据库中10条记录,在java程序中会将10条数据封装成10个java对象,然后将10个java对象放到一个集合中,将集合传输当前端。之后遍历集合,读取数据。 (拉货的货车)
  • 集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,集合当中存储的都是java对象的内存地址(存储的引用),因为集合是一个对象,对象内部存储的是其他类型数据的内存地址。
  • 在java中每一个不同的集合,底层会对应不同的数据结构,往不同的集合中存储元素,等于将数据放到了不同的数据结构当中,
    • 数据结构:数据的存储结构,不同数据结构,数据的存储方式不同
    • 数组、二叉树、链表、哈希表
    • new ArrayList(); //创建一个集合,底层是数组——将检索发挥到极致
    • new LinkedList(); //创建一个集合,底层是链表——将随机增删发挥到极致
  • java中集合分类
    • 单个方式存储元素:这一类集合的父接口:java.util.Collection;
    • 以键值对存储元素:这一类集合的父接口:java.util.Map ;

Collection接口

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

  • ArrayList集合底层采用的数据结构是数组。ArrayList是非线程安全。
  • LinkedList集合底层采用的数据结构是双向链表数据结构
  • Vetor集合底层采用的数据结构是数组。但是Vector是线程安全的,Vector所有的方法都有synchronized修饰,但是效率较低,所以Vector使用较少了。
  • HashSet底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key部分
  • TreeSet底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合的key部分
    在这里插入图片描述

  • List集合存储元素的特点:有序可重复——见例一
    • 有序:存进去的顺序和取出的顺序相同
    • 可重复:存进去1,可以再存储1
  • Set集合存储元素的特点:无序不可重复——见例一
    • 无序:存进去的顺序和取出的顺序不一定相同,Set集合没有下标
    • 不可重复:存进去1,不能再次存储1
  • SortedSet集合存储元素的特点:由于继承Set集合,所以他的特点是无序不可重复。但是放在SortedSet集合中的元素可以自动排序,称为可排序集合,放到该集合的元素是自动按照大小顺序排序的。
    • 可排序:可以按照大小顺序排序。

Map

  • Map集合和Collection没有关系
  • Map集合以key和value键值对的方式存储元素
  • key和value都存储java对象的内存地址。
  • 所有Map集合的key特点:无序不可重复。遍历Map时,重点是获得key。
    在这里插入图片描述
  • SortedMap集合的key存储元素的特点:无序不可重复,放入SortedMap集合key部分的元素会自动按照大小顺序排序,称为可排序集合。
  • TreeMp是一个二叉树结构
  • Properties是线程安全的,因为继承HashTable,存储元素采用key和value形式,且只能支持String类型,不支持其他类型。properties被称为属性类。
  • 在这里插入图片描述

Collection常用方法

在这里插入图片描述
JDK帮助文档

  • Collection存放元素类型
    • 未使用泛型之前,集合可以存放Object所有子类型
      (货车里面什么都装)。【集合不能直接存储基本数据类型,也不能存储java对象,只是存储了java对象的内存地址 Collection c =new ArrayList();】
    • 使用泛型之后,Collection只能存储某个具体的类型
  • Collection常用方法:
    • boolean add(E e) //添加
    • int size() // 返回此 collection 中的元素数。
    • void clear() //清空此 collection 中的所有元素(可选操作)。
    • boolean contains(Object o) //如果此 collection 包含指定的元素o,则返回 true。
    • boolean remove(Object o) //从 collection 中移除指定元素的单个实例
    • boolean isEmpty() //判断集合中元素的个数是否为“0”
    • Object[] toArray() //集合转数组
package Advance.gather;

import java.util.*;


/**
 * @author 衣鱼
 *	Collection常用方法
 *		boolean 	add(E e)
 *		int 	size()		// 返回此 collection 中的元素数。
 *		void 	clear()			//清空此 collection 中的所有元素(可选操作)。
 *		boolean 	contains(Object o)			//如果此 collection 包含指定的元素o,则返回 true。
 *		boolean 	remove(Object o) 			//从 collection 中移除指定元素的单个实例
 *		boolean 	isEmpty()			//判断集合中元素的个数是否为“0”
 *		Object[] 	toArray()			//集合转数组
 */
public class CollectionTest01 {
	public static void main(String[] args) {
		//创建一个Collection对象 ——错误
		//Collection是一个接口,接口是抽象的,无法实例化
		//Collection c = new  Collection();
		
		Collection c = new ArrayList();		//多态 父类型引用指向子类型对象
		c.add(1200);		//自动装箱 实际上放的是内存地址 Integer x =new Integer(1200);
		c.add(new Object());		//放的内存地址
		c.add(true);
		//获取集合中元素的个数
		System.out.println("集合中元素的个数"+c.size());		//3
		
		//清空元素
		c.clear();
		System.out.println("集合中元素的个数"+c.size());		//0
		
		//添加元素
		c.add("hello");
		c.add("world");
		c.add(1);
		
		//判断集合中是否包含1200
		System.out.println(c.contains("1200"));		//false
		System.out.println(c.contains("hello"));		//true
		System.out.println(c.contains("hello world"));	//false
		
		//删除元素
		c.remove(1);
		System.out.println("集合中元素的个数"+c.size());	//2
		
		//判断集合是否为空
																    /*@return <tt>true</tt> if this collection contains no elements
																    boolean isEmpty(); 
																     */
		System.out.println(c.isEmpty());		//false
		c.clear();
		System.out.println(c.isEmpty());		//true
		
		c.add("hello");
		c.add("world");
		c.add(1);
		
		//集合转换为数组  Object[] 	toArray()
		Object[] objs=c.toArray();
		for(int i =0;i<objs.length;i++) {
			System.out.print(objs[i]+"\t");		//hello	world	1	
		}
		
	}	
}

迭代/遍历理解

  • 当集合的结构发生改变之后,迭代器必须重新获取,否则会产生错误【ConcurrentModificationException】———见迭代 remove
  • Iterator中的方法
    • boolean hasNext() //如果仍有元素可以迭代,则返回 true。
    • Object next() //返回迭代的下一个元素。
    • void remove() // 从迭代器指向的 collection 中移除迭代器返回的最后一个元素
      在这里插入图片描述
package Advance.gather;

import java.util.*;

/**
 * @author 衣鱼			******
 *		关于集合遍历/迭代	——该实验的迭代方式是所以Collection通用的方式
 *												在Map集合中不能用,在所有Collection子类中使用
 *		Iterator中的方法
 *			boolean 	hasNext() 	//如果仍有元素可以迭代,则返回 true。
 *			Object 	next()		//返回迭代的下一个元素。
 *			void 	remove()			// 从迭代器指向的 collection 中移除迭代器返回的最后一个元素
 */
public class CollectionTest02 {
	public static void main(String[] args) {
		//创建集合对象
		Collection c = new  ArrayList();
		 //添加元素
		c.add("abc");
		c.add("def");
		c.add(100);
		c.add(new Object());
		
		//对集合进行遍历
			//①获取集合对象的迭代器对象Iterator
		Iterator it =c.iterator();		//拿到迭代器,利用迭代器的方法遍历集合
			//②利用迭代器对象开始迭代
		//boolean hasNext = it.hasNext();
		while(it.hasNext()){		//如果hasNext为true执行
				Object obj = it.next();
				
				System.out.println(obj);
		}
	}
}

在这里插入图片描述

ArrayList;HashSet 的有序性、重复性理解
package Advance.gather;

import java.util.*;

/**
 * @author 衣鱼
 *		ArrayList:有序 、可重复
 *		HashSet:无序、不可重复
 */
public class CollectionTest03 {
	public static void main(String[] args) {
		Collection c1 =new ArrayList();		//ArrayList:有序 、可重复
		c1.add(1);
		c1.add(2);
		c1.add(3);
		c1.add(4);
		c1.add(1);
		//创建Iterator对象
		Iterator it =c1.iterator();
		while(it.hasNext()) {
			System.out.print(it.next()+"\t");	//1	2	3	4	1	
		}
		System.out.println();
		Collection c2 =new HashSet();			//HashSet:无序、不可重复
		c2.add(1);
		c2.add(4);
		c2.add(2);
		c2.add(8);
		c2.add(4);
		Iterator tt =c2.iterator();
		while(tt.hasNext()) {
			System.out.print(tt.next()+"\t");		//1	2	4	8	
		}
	}
}

迭代—remove
  • 在迭代集合元素的过程中,不能调用集合对象的remove方法,删除元素。
  • 迭代器相当于对当前集合的状态拍了一个快照,迭代器迭代的时候,会参照这个快照进行迭代,一旦快照和真实的集合状态不匹配【remove】,就会出现问题。而通过【迭代器.remove()方法】时 ,快照的状态也发生了改变。保持和集合的真实状态一致。
  • 集合结构只要发生改变,迭代器必须重新获取.
package Advance.gather;

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

public class CollectionTest06 {
	public static void main(String[] args) {
		Collection c =new ArrayList();
		//获取迭代器,错误,此时尚未添加元素,获取的迭代器
		//指向集合中没有元素的情况
		//集合结构只要发生改变,迭代器必须重新获取
		//Iterator it =c.iterator();
		
		c.add(1);
		c.add(2);
		c.add(3);
		Iterator it =c.iterator();
		while(it.hasNext()) {
			Object obj = it.next();
			//删除元素
			//删除元素之后,集合的结构发生变化,应该重新获取迭代器
			//但是循环到下一次并没有重新获取迭代器,所以出现异常
			//c.remove(obj);
			System.out.println(obj);
		}
	}
}

contains深入理解:底层调用equals

  • contains是判断集合中是否包含某个元素的方法
  • 底层的运行原理:调用equals方法
  • 即:如果放在集合中的元素,是自己创建的引用类型,Student类、teacher类,需要重写equals方法!!!
package Advance.gather;

import java.util.*;

/**
 * @author 衣鱼
 *		深入理解Collection集合的contains方法
 *			boolean contains(Object o)		//判断集合中是否包含某个对象o
 */
public class CollectionTest04 {
	public static void main(String[] args) {
		//创建Collection对象
		Collection c=new ArrayList();
		
		String s1 = new String("abc");
		c.add(s1);
		
		String s2 = new String("def");
		c.add(s2);
		
		System.out.println("元素的个数是"+c.size());
		
		String x =new String("abc");
		/**问题:c集合是否包括x?
				包含的含义:
						c集合所指向的ArrayList中,是否添加了X——没有添加,如果contains是对比x,那么结果会输出false
						c集合所指向的ArrayList中,是否add了引用x所指向的对象”abc“ —— x 和 s1 都是指向“abc”的引用
				
		*/
		System.out.println(c.contains(x));			//true
		x.equals(s1);
		/**
		 * String重写的equals方法不比较内存地址,比较的是引用所指向的对象(内容)
		 * 	输出实验结果表明,contains方法底层调用了equals。
		 * */
		System.out.println(c.contains(x));			//true
	}
}

在这里插入图片描述
remove底层调用equals方法!!

package Advance.gather;

import java.util.ArrayList;
import java.util.Collection;

/**
 * @author 衣鱼
 *	remove()
 */
public class CollectionTest05 {
	public static void main(String[] args) {
		//创建Collection对象
				Collection c=new ArrayList();
				
				String s1 = new String("hello");
				c.add(s1);
				
				String s2 = new String("hello");
				
				//删除s2
				c.remove(s2);
				//
				System.out.println("元素的个数是"+c.size());
	}
}

list

在这里插入图片描述

  • list接口
    • 存储元素特点:有序可重复 ,有下标,从0开始 以1递增。
    • list是Collection的子接口,List的特有方法
      • E get(int index) //利用下标获取元素,因为list集合拥有下标,所以list有自己特殊的遍历方式——下标遍历。
      • int indexOf(Object o) //获取指定对象第一次出现的索引
      • E set(int index, E element) //修改指定目标的元素
package Advance.gather;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
 * @author 衣鱼
 *	List特有方法:
 *		  E 	get(int index)
 *		  int 	indexOf(Object o)
 *		  E 	set(int index, E element) 
 */
public class ListTest01 {
	public static void main(String[] args) {
		List myList = new ArrayList();
		myList.add("A");
		myList.add("B");
		myList.add("C");
		myList.add("D");
		//在列表指定位置添加元素
		myList.add(1,"KING");		//在下标1处添加“KING”
		
		//迭代
		Iterator it = myList.iterator();
		while(it.hasNext()) {
			Object elt  = it.next();
			System.out.println(elt);
		}
		
		//根据下标获取元素
		Object o =myList.get(1);
		System.out.println(o);
		 
		
		//List有下标,所以List集合可以根据下标进行遍历
		for(int i =0;i<myList.size();i++) {
			Object fristObj = myList.get(i);
			System.out.print(fristObj+"\t");
		}
		System.out.println();
		
		//获取指定对象第一次出现的索引
		System.out.println(myList.indexOf("KING"));		//1
		
		//获取指定对象最后一次出现处的索引
		System.out.println(myList.lastIndexOf("C"));		//3
		
		//删除指定下标的元素  
		myList.remove(1);
		for(int i =0;i<myList.size();i++) {
			Object fristObj = myList.get(i);
			System.out.print(fristObj+"\t");
		}
		
		//修改指定目标的元素
		myList.set(2, "soft");
		for(int i =0;i<myList.size();i++) {
			Object fristObj = myList.get(i);
			System.out.print(fristObj+"\t");
		}
	}
}

ArrayList

  • ArrayList初始化容量是10(底层先创建一个长度为0的数组,当添加第一个元素的时候,初始化容量10)
  • ArrayList集合的扩容是原容量的1.5倍。是原容量的二进制向右移一位。
  • ArrayList底层是Object类型的数组,优化:尽可能少的扩容,因为数组扩容效率比较低,建议预先估计所需容量,定义预估计的容量。 List list1 =new ArrayList(200); 减少扩容次数。
  • ArrayList构造方法可以将Collection转化为ArrayList。
    • ArrayList(Collection<? extends E> c) //构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
package Advance.gather;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

public class ArrayListTest01 {
	public static void main(String[] args) {
		//默认初始化容量是10
		List list1 =new ArrayList();
		//指定初始化容量
		List list2 =new ArrayList(100);
		
		//创建HashSet集合
		Collection c =new HashSet();
		c.add(100);
		c.add(200);
		c.add(900);
		c.add(50);
		
		//HashSet集合转换为List集合
		List list3 = new ArrayList(c);
		
		//循环输出转换后的list3集合
		for(int i =0;i<list3.size();i++) {
			Object obj =list3.get(i);
			System.out.println(obj);
		}
	}
}

LinkList

  • linkList实际上底层是双向链表,具有链表的属性

    • 链表优点:由于链表的元素在存储空间内存地址上不是连续的,所以随机增删不会有大量的元素移动,因此随机增删效率较高
    • 链表缺点:不能通过数学表达式计算找到元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止,所以链表的查找/检索效率低。
  • 单向链表
    在这里插入图片描述

vector

  • Vector底层是一个数组,初始容量是10。

  • Vector扩容是原容量是2倍:10——20——40——80

  • Vector所有方法中都是线程同步的,都带有synchronized关键字,是线程安全的,但是效率较低

  • 如何将一个线程不安全的ArrayList集合转化成线程安全的

    • 使用集合工具类:java.util.Collections;
      在这里插入图片描述

泛型

  • JDK5.0之后 推出的新特性

  • 泛型属于编译期间的新特性

  • 使用泛型之后的优点

    • 集合存储的元素类型统一
    • 从集合中取出的元素类型是泛型的指定类型,不需要大规模的“向下转型”
  • 使用泛型的缺点:导致集合存储元素缺乏多样性

  • List myList = new ArrayList(); 在JDK8之后,泛型引入了自动类型推断机制(钻石表达式)—— List myList = new ArrayList<>();
    在这里插入图片描述

package Advance.gather;

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

public class GenericTest01 {
	public static void main(String[] args) {
		//未使用泛型之前
			/*
			//创建集合
			List myList = new ArrayList();
			
			//构造对象
			Cat c = new Cat();
			Brid b = new Brid();
			
			//将对象放入集合当中
			myList.add(c);
			myList.add(b);
			myList.add(1);
			
			//遍历集合,使集合中的所有动物移动
			Iterator it = myList.iterator();
			while(it.hasNext()) {
				//Animal a =it.next();  //错误
				Object obj = it.next();	//使用迭代器取出的就是Object类型
				//obj中没有move方法,无法直接调用,需要向下转型
				if (obj instanceof Animal) {
					Animal a = (Animal) obj;
					a.move();
				} 	
			}
			*/
		
		//使用泛型之后
		//使用泛型指定集合中的类型
		//List<Animal> :List集合中只允许存储Animal类型的数据 ——类型更统一
		List<Animal> myList = new ArrayList<Animal>();
		//指定完成后,说明myList中只能存储Animal,不能存储String等其他类型,否则报错
		//myList.add("1");		//错误
		Cat c = new Cat();
		Brid b = new Brid();
		
		myList.add(c);
		myList.add(b);
		
		//迭代器迭代Animal类型
		Iterator<Animal> it  = myList.iterator();
	
		while(it.hasNext()) {
			//所有动物移动
			//Animal a = it.next();
			//a.move();	
			
			//猫抓老鼠,鸟儿飞翔——仍需要转型
			Animal a = it.next();
			if(a instanceof Cat) {
				((Cat) a).catchmouse();
			}
			if(a instanceof Brid){
				((Brid)a).fly();
			}
		}
	}
}

//父类
class Animal{
	public void move() {
		System.out.println("动物在移动!");
	}
}

class Cat extends Animal{
	public void catchmouse() {
		System.out.println("猫在捉老鼠!");
	}
}

class Brid extends Animal{
	public void fly() {
		System.out.println("鸟儿在飞翔!");
	}
}

自定义泛型

在这里插入图片描述

foreach 增强for循环

  • JDK5之后的新特性

  • 语法:

  • for(元素类型 变量名 : 数组或集合){ //变量名代表是数组/集合中的每个元素
    System.out.println(变量名);
    }
    在这里插入图片描述


public class GennericTest03 {
	 public static void main(String[] args) {
		int[] arr = {23,425,664,25,2448,2468};
		
		//遍历数组 (普通for循环)
		for(int i =0;i<arr.length ;i++) {
			System.out.println(arr[i]);
		}
		System.out.println("===========================");
		
		//foreach 增强for循环
		//foreach缺点:没有下标
		/*语法:
		 * 		for(元素类型 变量名 : 数组或集合){
		 * 			System.out.println(变量名);
		 * 		}
		 * */
		for(int data:arr) {
			//data 代表是数组中的每个元素
			System.out.println(data);
		}
	}
}

  • 集合使用foreach
import java.util.ArrayList;
import java.util.List;

	//集合使用foreach
public class GennericTest04 {
	 public static void main(String[] args) {
		//创建集合
		 List<String> myList = new ArrayList<>();
		 //添加元素
		 myList.add("asd");
		 myList.add("fgh");
		 myList.add("jkl");
		 myList.add("qaz");
		 
		 //遍历集合
		 for(String data : myList) {
			 System.out.println(data);
		 }
	}
}

Set

在这里插入图片描述

  • Set集合存储元素的特点:无序不可重复——见例一
    • 无序:存进去的顺序和取出的顺序不一定相同,Set集合没有下标
    • 不可重复:存进去1,不能再次存储1
  • SortedSet集合存储元素的特点:由于继承Set集合,所以他的特点是无序不可重复。但是放在SortedSet集合中的元素可以自动排序,称为可排序集合,放到该集合的元素是自动按照大小顺序排序的。
    • 可排序:可以按照大小顺序排序。
    • HashSet 的add方法底层是HashMap的key部分
    • TreeSet的add方法底层是TreeMap的key部分
      在这里插入图片描述

HashSet

  • HashSet初始化容量为16,初始化建议为2 的倍数。扩容是原容量*2+1.

TreeSet

  • TreeSet集合底层实际上是一个TreeMap
  • TreeMap集合底层是一个二叉树
  • 放到TreeSet集合的元素等同于放到TreeMap集合的Key部分
  • TreeSet集合中的元素:无序不可重复,但是可以按照元素大小顺序进行自动排序,称为可排序集合——数据库查询时,升序或者降序排列。
  • TreeSet无法对自定义的类型进行排序。程序运行出现异常:java.lang.ClassCastException :Advance.gather.Person cannot be cast to java.lang.Comparable
  • 对自定义的类型排序的两个方法:Comparable接口实现、Comparator接口实现
    • 当规则不会发生改变的时候,或者说比较规则只有一个的时候,适合使用Comparable
    • 当规则有多个,并且多个规则之间频繁切换,适用Comparator接口
排序Comparable接口实现
  • compareTo重写前
package Advance.gather;
//compareTo重写前
import java.util.TreeSet;

/**
 * TreeSet对自定义的类型不能排序
 * 		因为没有指定Person对象之间的比较规则
 * 		程序运行出现异常:java.lang.ClassCastException :Advance.gather.Person cannot be cast to java.lang.Comparable
 * */
public class TreeSetTest01 {
	public static void main(String[] args) {
		//生成对象
		Person p1 = new Person(22);
		Person p2 = new Person(52);
		Person p3 = new Person(16);
		Person p4 = new Person(42);
		
		//创建TreeSet集合
		TreeSet<Person> person = new TreeSet<>();
		
		//添加元素
		person.add(p1);		//TreeSet调用add方法,底层调用TreeMap的put方法
		person.add(p2);
		person.add(p3);
		person.add(p4);
		
		//遍历集合
		for(Person p : person) {
			System.out.println(p);		//输出的是Set集合person的元素 每个元素都是Person
														//输出的时候调用toString方法,需要重写该方法
		}
	}
}

class Person{
	int age;
	public Person(int age) {
		this.age=age;
	}
	//重写toString方法
	public String toString() {
		return "person[age="+age+"]";
	}
}
  • compareTo重写后

    • 需要在compareTo方法中编写比较的逻辑:告诉编译器按照什么进行比较
    • k.compareTo(t.key)
    • 拿着参数k和集合中的每一个k进行比较,返回值:=0、<0、>0、
    •  返回0 表示相同 value会覆盖
      
    •  返回>0 会继续在右子树上找
      
    •  返回<0 会继续在左子树上找
      

    在这里插入图片描述

package Advance.gather;

import java.util.TreeSet;

/**
 * TreeSet对自定义的类型不能排序
 * 		因为没有指定Person对象之间的比较规则
 * 		程序运行出现异常:java.lang.ClassCastException :Advance.gather.Person cannot be cast to java.lang.Comparable
 * */
public class TreeSetTest02 {
	public static void main(String[] args) {
		//生成对象
		Person p1 = new Person(22);
		Person p2 = new Person(52);
		Person p3 = new Person(16);
		Person p4 = new Person(42);
		
		//创建TreeSet集合
		TreeSet<Person> person = new TreeSet<>();
		
		//添加元素
		person.add(p1);		//TreeSet调用add方法,底层调用TreeMap的put方法
		person.add(p2);
		person.add(p3);
		person.add(p4);
		
		//遍历集合
		for(Person p : person) {
			System.out.println(p);		//输出的是Set集合person的元素 每个元素都是Person
														//输出的时候调用toString方法,需要重写该方法
		}
	}
}

//放在TreeSet集合的元素需要实现java.lang.Comparable接口
//实现compareTo方法 equals可以不写
class Person implements Comparable<Person>{		//实现接口
	int age;
	public Person(int age) {
		this.age=age;
	}
	//重写toString方法
	public String toString() {
		return "person[age="+age+"]";
	}
	
	/**
	 * 需要在compareTo方法中编写比较的逻辑:告诉编译器按照什么进行比较
	 * k.compareTo(t.key)
	 * 拿着参数k和集合中的每一个k进行比较,返回值:=0、<0、>0、
	 * 	 	返回0 表示相同 value会覆盖
	 * 		返回>0 会继续在右子树上找
	 * 		返回<0 会继续在左子树上找
	 * */
	@Override
	public int compareTo(Person o) {			//o1.compareTo(o2);  
																	//o1就是this
																	//o2就是传入的o
		return this.age-o.age;
	}
}
排序Comparator接口实现
  • 单独编写一个比较器
  • 比较器实现java.util.Comparator接口
  • Comparable是java.lang包下的 。Comparator是java.util包下的
    在这里插入图片描述
package Advance.gather;

import java.util.Comparator;
import java.util.TreeSet;

/**
 * TreeSet集合中元素可排序的第二种方式:使用比较器
 * 
 * */
public class TreeSetTest03 {
	public static void main(String[] args) {
		//创建Set集合时,需要使用比较器
		//TreeSet<Customer> Customer = new TreeSet<>();	//未调用编写的比较器
		
		//给构造方法传递一个比较器
		TreeSet<Customer> customer = new TreeSet<>(new CustomerComparator());
		customer.add(new Customer(25));
		customer.add(new Customer(54));
		customer.add(new Customer(15));
		customer.add(new Customer(9));
		
		for(Customer c : customer) {
			System.out.println(c);
		}
	}
}

class Customer{
	int age;
	public Customer(int age) {
		this.age=age;
	}
	//重写toString方法
	public String toString() {
		return "Customer [age ="+age+"]";
	}
}

//单独编写一个比较器
//比较器实现java.util.Comparator接口
//Comparable是java.lang包下的 。Comparator是java.util包下的

class CustomerComparator implements Comparator<Customer>{

	public int compare(Customer o1, Customer o2) {
		//指定比较规则:按照年龄排序
		return o1.age-o2.age;
	}
	
}

Collections 集合工具类

  • Collection 属于java.util 集合接口
  • Collections 属于工具类 ,方便集合操作
    • 转换成线程安全
    • 排序
package Advance.gather;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class CollectionsTest01 {
	public static void main(String[] args) {
		//ArrayList集合不是线程安全的
		List<String> list = new ArrayList<>();
		 
		//转换为线程安全的
		Collections.synchronizedList(list);
		
		//排序:sort方法针对List集合
		//对List集合进行排序,需要确保List集合实现了Comparable接口
		Collections.sort(list);
		
	
	}
}

Map详解

  • 常用方法
    • boolean containsKey(Object key)
    • boolean containsValue(Object value)
    • boolean isEmpty() //如果此映射未包含键-值映射关系,则返回 true。
    • Set<Map.Entry<K,V>> entrySet() // 返回此映射中包含的映射关系的 Set 视图。——将Map集合转为Set集合,转换成的Set集合元素类型为Map.Entry<K,V> 【Map的静态内部类】
    • V get(Object key) //返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。——通过Key 获取value。
    • void clear() //从此映射中移除所有映射关系(可选操作)。——清空集合
    • Set keySet() // 返回此映射中包含的键的 Set 视图。
    • V remove(Object key) //如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
    • int size() //返回此映射中的键-值映射关系数。
    • V put(K key, V value) //将指定的值与此映射中的指定键关联(可选操作)——添加键值对
      在这里插入图片描述
package Advance.gather;

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

public class MapTest01 {
	public static void main(String[] args) {
		//创建Map集合
		Map<Integer ,String> maMap = new HashMap<>();
		//添加元素
		maMap.put(1,"zhangsan");
		maMap.put(2,"lisi");
		maMap.put(3,"wangwu");
		maMap.put(4,"zhaoliu");
		maMap.put(5,"zhangsan");
		
		//通过key获取value
		String str = maMap.get(1);
		System.out.println("键“1”对应的值为"+str);
		
		//获取键值对的数量
		System.out.println("键值对的数量 :"+maMap.size());
		
		//判断是否包含某个键
		System.out.println(maMap.containsKey(5));
		
		//判断是否包含某个值
		System.out.println(maMap.containsValue("zhangsan"));
		
		//通过键删除键值对
		maMap.remove(1);
		
		//获取所有的value
		Collection<String> value = maMap.values();
		for(String s : value) {
			System.out.println(s);
		}
	}
}

☆☆☆Map遍历☆☆☆

  • 通过key值 通过获取key值,遍历所有的value
package Advance.gather;

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

public class MapTest02 {
	public static void main(String[] args) {
		//方法一:获取key值,遍历所有的value
			//创建Map集合
			Map<Integer ,String> map = new HashMap<>();
			//添加元素
			map.put(1,"zhangsan");
			map.put(2,"lisi");
			map.put(3,"wangwu");
			map.put(4,"zhaoliu");
			map.put(5,"zhangsan");
			
			//获取所有key值
			Set<Integer> keys = map.keySet();
			//遍历key
				//迭代器
				Iterator<Integer> it = keys.iterator();
				while(it.hasNext()) {
					Integer key =it.next();		//迭代获取key值
					String value = map.get(key);		//由map中key值获取vlaue值
					System.out.println(value);
				}
				//foreach循环
				for(Integer key :keys) {
					String vlaue2 = map.get(key);
					System.out.println(vlaue2);
				}

			//方法二:Set<Map.Entry<K,V>> 	entrySet()	
			//将Map集合直接全部转换为Set集合
			//Set集合中元素的类型:Map.entry
			Set<Map.Entry<Integer, String>> set = map.entrySet();
				//遍历set
				Iterator<Map.Entry<Integer, String>>  its = set.iterator();
				while(its.hasNext()) {
					Map.Entry<Integer, String> entry =its.next();		//取出了的一个结点:node对象
					//调用结点entry的get方法 得到key、value
					Integer key = entry.getKey();
					String vlaue = entry.getValue();
				}
				//foreach循环——————————效率较高
				for(Map.Entry<Integer, String> entry : set) {
					System.out.println(entry.getKey()+"-------->"+entry.getValue());
				}
	}
}

在这里插入图片描述

  • Map遍历第二种方法 :Set<Map.Entry<K,V>> entrySet()
    在这里插入图片描述在这里插入图片描述
HashMap
  • HashMap集合底层是哈希表/散列表的数据结构,且key值和value都可以为null。但是HashTable的key、value都不能为null,会出现空指针异常。
  • 哈希表:
    • 哈希表是一个数组和单向链表的结合体
    • 数组:在查询方面效率高,随机增删方面效率低
    • 单向链表:在随机增删方面效率高,查询效率低
    • 哈希表集两者之长,发挥优点。
  • HashMap集合的默认初始化容量为16,默认加载因子是0.75。意为当HashMap集合底层数组容量达到75%的时候,数组开始扩容。扩容之后的容量是原来容量的2倍。
  • HashMap集合初始化最好是2的幂数,提高hash的存取效率。
  • 在JDK8之后,如果Hash表单向链表的元素超过8个,单向链表会变成红黑树数据结构。当红黑树上的结点小于6时,红黑树数据结构会变回单向链表。
  • HashMap的源代码
    在这里插入图片描述
  • HashMap的存取元素的原理
    在这里插入图片描述在这里插入图片描述蜘蛛纸牌
  • 重点:放在HashMap集合的key部分元素,以及放在HashSet集合中的元素,都需要重写HashCode和equals方法。——编译器生成
    • HashCode是生成哈希值的,哈希值用作数组下标,所以存取时,先调用hashCode,当数组下标一样时,进行同一数组下标的链表equals比较。
    • 如果一个类的equals方法重写了,那么hashCode方法必须重写。如果该类的equals结果返回ture,那么hashCode返回结果应当一样。
HashTable
  • HashTable是线程安全的
  • HashTable和HashMap一样底层都是哈希表
  • HashTable初始化容量为11,默认加载因子0.75。HashTable的扩容是原容量*2+1.【即原容量的二进制右移一位】
  • HashTable是线程安全的
  • properties
package Advance.gather;

import java.util.Properties;

/**
	 * Properties是Map集合,被称为属性类对象
	 * 继承HashTable,是线程安全的。
	 * Properties的key和value都是String类型
	 * 
	 * 掌握properties两个方法:存、取
	 * */
public class PropertiesTest01 {
	public static void main(String[] args) {
		Properties pro = new Properties();
		//存:.setProperty
		pro.setProperty("user1", "qwerthbujbue");
		pro.setProperty("user2", "qwwatghgujbue");
		pro.setProperty("user3", "waghbvrjshgf");
		pro.setProperty("user4", "thguytlkjhgfeu");
		//取:通过key获取value
		String user1 = pro.getProperty("user1");
		String user2 = pro.getProperty("user2");
		String user3 = pro.getProperty("user3");
		String user4 = pro.getProperty("user4");
		
		System.out.println(user1);
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值