Day14 学习java(散列表和泛型)

本文介绍了Java中的散列表(哈希表)数据结构,讲解了HashSet的添加过程,包括哈希算法和冲突解决。同时,探讨了Map接口的实现,如HashMap和TreeMap,强调了HashMap的底层原理。此外,文章还详细阐述了泛型的概念、使用方式及其优缺点,并给出了自定义泛型的说明。最后,提出了一道关于Map按照Value排序的小练习。
摘要由CSDN通过智能技术生成

Set

HashSet使用

public class Collection_01 {

	public static void main(String[] args) {
		HashSet set = new HashSet();
		set.add(1);
		set.add("abc");
		System.out.println(set);
		set.remove("abc");
		for (Object o : set) {
			System.out.println(o);
		}
	}

}

在这里插入图片描述

散列表

散列表又称哈希表,是一种数据结构,特点是元素的关键字与其存储地址直接相关。不同的关键字通过散列函数映射到同一个值,则称它们为"同义词"。通过散列函数确定的位置已经存放了其他元素,称这种情况为"冲突"

概述

可以理解为:数组中保存的是链表的首节点,用来保存k和v键值对
hash算法:是一种安全的加密机制,可以把不定长数据转换为定长数据,并且不能保证其唯一性,又叫哈希冲突,在java中,指的就是hashCode方法

k可重复,v不可重复
添加过程:

  • 1.根据要添加的key,调用的它的hashCode方法,生成hash值

  • 2.通过一定的算法,根据hash值生成数组的下标

  • 3.判断该下标中是否有数据,如果没有数据就把该键值对映射关系保存到数组中

  • 4.如果该下标中有数据,则调用key的equals方法,和对应的所有数据进行比较,如果不相等,则添加到链表的尾部即可

  • 5.如果对应的链表中,通过equals方法比较的时候发现了相同的数据,那么key不再添加,但是value值会更新替换原来的值

在1.8中有个新改动,为了提高查询效率,引入了红黑树和扩容的优化,因为链表在查询性能上较差,所以每个数组中的链表个数如果大于等于7,则会把该链表转换为红黑树
数组默认初始化容量为16
底层实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Hashset

在这里插入图片描述
在这里插入图片描述
以上两个截图可看出来,当我们使用HashSet的时候,其实就等于是再使用HashMap
添加数据的时候,虽然调用的是HashSet的add方法,但是本质还是调用map的put方法
Ps : 在map中,put是添加操作
而 map中 需要保存的是k和v映射关系,所以在set中有一个变量保存了value的值
所以我们再进行set添加的时候,只操作了map中的key,value值我们不再关心

Map

概述

  • Map是无序的,并且保存的是K-V键值对映射关系,其中K不能重复,V可重复
  • HashMap:底层是散列表
  • TreeMap:底层是红黑树,元素必须按照一定的规则进行排序

继承体系

在这里插入图片描述

常用方法

在这里插入图片描述

HashMap

public class Map_01 {

	public static void main(String[] args) {
		// 创建map
		HashMap map = new HashMap();
		// 添加k-v
		map.put("A", "one");
		map.put("B", "two");
		map.put(65, 100);
		map.put('A', "three");
		// key重复,不添加,value替换
		map.put("A", "five");
		// 支持k和v都是null,但是没意义
		map.put(null, null);
		System.out.println(map);
		// 个数
		System.out.println(map.size());
		// 获取所有的value,并放到集合中返回
		Collection values = map.values();
		System.out.println(values);
		
		// get:根据K获取V的值
		System.out.println(map.get('A'));
		// 判断是否包含某个key
		System.out.println(map.containsKey(65));
		// 判断是否包含某个value
		System.out.println(map.containsValue(null));
		// 根据key删除映射关系,会返回对应的value值
		System.out.println(map.remove(null));
		System.out.println(map.containsValue(null));
		for (Object o : values) {
			System.out.print(o + "   ");
		}
		System.out.println("\n=============");
		// keySet:获取所有的key,封装到set对象中并返回
		Set keys = map.keySet();
		for (Object o : keys) {
			System.out.print(o + " : " + map.get(o) + "  ");
		}
		System.out.println();
		// 把map转换为set
		// Entry类中,保存了K和V两个变量,把map中的k和v转换为entry类的对象进行存储
		// 所以我们只需要保存entry对象,就等于保存了k和v
		Set set = map.entrySet();
		System.out.println(set);
		System.out.println();
		for (Object o : set) {
			System.out.println(o);
			// 转换为entry类型
			Entry entry = (Entry) o;
			// 获取k和v
			System.out.println(entry.getKey() + "  :  " + entry.getValue());
		
		}
	}

}

在这里插入图片描述

TreeMap

TreeMap 保存的元素会按照一定规则进行排序,底层是红黑树

public class Map_TreeMap {

	public static void main(String[] args) {
		TreeMap map = new TreeMap();
		// 添加自定义类型,并且A中实现了Comparable类
		map.put(new A("苹果", 5.5), 5);
		map.put(new A("橘子", 4.5), 10);
		System.out.println(map);
		// 添加已有类,且该类实现了Comparable接口,Integer默认升序

		map.clear();
		map.put(3, "a");
		map.put(1, "b");
		Set set = map.entrySet();
		System.out.println(set);
		set.clear();
		// 如果该类没有实现Comparable接口,或者我们想要降序,则需要使用Comparator
		map = new TreeMap(new Comparator() {

			@Override
			public int compare(Object o1, Object o2) {
				Integer i1 = (Integer) o1;
				Integer i2 = (Integer) o2;
				return i2 - i1;
			}

		});
		map.put(11, "a");
		map.put(2, "b");
		map.put(23, "c");
		map.put(3, "d");
		System.out.println(map);
	}
}

class A implements Comparable {
	private String name;
	private double price;

	public A(String name, double price) {
		this.name = name;
		this.price = price;
	}

	@Override
	public String toString() {
		return " [name=" + name + ", price=" + price + "]";
	}

	@Override
	public int compareTo(Object o) {
		if (o instanceof A) {
			A a = (A) o;
			if (this.price > a.price)
				return 1;
			else
				return -1;
		}
		return 0;
	}

}

在这里插入图片描述

泛型

概述

泛型:在编译过程中检测数据类型是否匹配
泛型必须是引用类型,不能使用基本类型
优点:统一了数据类型,减少了类型转换
缺点:只能保存同一种类型

使用方式

public class Map_04_Generic_01 {

	public static void main(String[] args) {
		// 没有使用泛型
		List list1 = new ArrayList();
		// 啥都能放
		list1.add(new B());
		list1.add("abd");
		// 取的时候,拿到的是Object
		for (Object o : list1) {
			// 需要判断和向下转型
			if (o instanceof B) {
				B b = (B) o;
				b.m1();
			}
		}
		// 使用泛型规定集合中只能保存B类
		List<B> list2 = new ArrayList<B>();
		list2.add(new B());
		// ↑添加其他元素报错,而且是编译的时候就报错
		// list2.add(2);
		// 使用的时候,拿到的就是A类型,不会出现类型转换异常
		for (B b : list2) {
			b.m1();
			;
		}
		// 泛型不能写基本类型,只能写引用类型,如果想保存基本类型,则需要编写对应的包装类类型
		// List<int>list3=new ArrayList<int>();
		List<Integer> list4 = new ArrayList<Integer>();
		// 如果需要保存多种数据,则不需要使用泛型
		// 但是如果需要保存同一种类型的数据,则一定要使用泛型,这样方便操作
		// set map使用泛型
		Set<String> set = new HashSet<String>();
		Map<String, String> map = new HashMap<String, String>();
	}
}

class B {
	public void m1() {
		System.out.println("m1执行了");
	}
}

在这里插入图片描述

注意

泛型不能写基本类型,只能写引用类型

自定义范式

定义泛型,使用大写字母A-Z表示,写什么都一样,都只是占位符而已,只不过,某些占位符也有一些特殊的含义

  •  E : Element 一般代表元素,而集合中的数据 我们叫元素,所以在集合中出现的泛型一般使用E表示
    
  •  K : Key 表示键
    
  •  V : value 表示值 K和V一般在散列表中出现(Map)
    
  •  T : Type 表示一个java类型
    
  •  N : 表示Number
    
  •  ? : 表示不确定的类型
    

如果规定了泛型,但是使用的地方没有指定泛型,则默认是Object类型
在这里插入图片描述

小练

Map 以Value排序
Map是没有办法按照Value排序的,因为源码中写死了用Key进行比较
所以只能保存到List中进行排序

public class Map_06 {

	public static void main(String[] args) {
		Map<String, Integer> map = new TreeMap<String, Integer>();
		map.put("b", 11);
		map.put("a", 21);
		map.put("c", 145);
		map.put("d", 41);
		map.put("e", 15);
		System.out.println(map);
		// 把map封装到entry中并保存到set中
		Set set = map.entrySet();
		// 把set保存到list中,通过ArrayList的有参构造可以直接把set转换为List
		List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(
				set);
		Collections.sort(list, new Comparator<Entry<String, Integer>>() {

			@Override
			public int compare(Entry<String, Integer> o1,
					Entry<String, Integer> o2) {

				return o1.getValue() - o2.getValue();
			}

		});
		System.out.println(list);
	}

}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值