首先要清楚这两个都是数据结构,就像是两个容器,应用场景:专门用来搜索。Tree就是一个二叉搜索树,Map和Set是两个容器,可以存放数据。Map是一个单独的接口,Set接口是拓展了collection接口的。
二叉搜索树的概念:左树节点值比根节点值小,右树的节点值比根节点大,每颗子树又是一颗搜索树。
Map:是一个单独的接口类,里边存放的数据结构是K-V键值对的方式。(key-value),也就是说每一个key值都对应的有一个value值。
所以我们可以用Map接口new一个对象看一下Map中这些方法是如何使用以及在什么情况下使用Map或者Set。
public static void main1(String[] args) {
/*Map是一个接口,用接口的引用创建一个对象,treeMap底层是一个搜索树
* */
Map<String,Integer> treeMap= new TreeMap<>();
treeMap.put("hello",3);//往里边存放数据,Key-value的形式存储
treeMap.put("the",8);//比较的时候是用key去比较的
treeMap.put("abc",4);
System.out.println(treeMap);//重写了toString方法
Integer val = treeMap.get("abc");//给一个key值,返回相对应的val值
//如果treeMap中没有这个val值,就是null
//还有就是如果没有这个key值可以给定一个默认值
Integer val1 = treeMap.getOrDefault("hello44",100);
System.out.println(val1);
//keySet方法可以将treeMapp中存放的值进行输出,但是没有顺序,是乱序存放的
Set<String> keySet = treeMap.keySet();
System.out.println(keySet);
/*Map.Entry<String,Integer> 他是一个类似节点这样的类型,就像是node,Entry是
* 一个接口,它的里面也有方法,map也是一个接口,有点类似外部类.内部类这样,entrySet
* 这个方法可以将里面存放的key值和value值放进另一个麻袋中,然后可以遍历这个麻袋进行
* 输出拿到key值和value值,是Map中一个用来存放键值对的映射关系的一个内部类*/
Set<Map.Entry<String,Integer>> set = treeMap.entrySet();
for (Map.Entry<String,Integer> entry : set) {
System.out.println("key: "+entry.getKey() + " value: "+entry.getValue());
}
可以看到Map中有很多的方法:简单介绍一下几种常用的,首先是put方法,就是往map中存放数据的,以key-value键值对的方式存储,new对象的时候可以用泛型指定key和val的类型。
还可以用get方法去获取里边的数据,在get方法中给一个key值,就可以返回对应的value值,如果map中没有这个key值,就返回一个null。
getorDefault方法:给key值设置默认的value值,返回值就是给key设置的value值。
keySet方法:可以输出map中存放的key值。(一定重写了toString方法)
Map.Entry的使用:他是Map中的一个内部类,主要反应map存放的数据的k-v关系,可以用来获取键值对,然后可以设置value和key的比较方式。(它有点类似于链表中node节点这样的内部类,用的使用就是外部类.内部类,Map是一个接口,然后它也是一个接口)
如上图:Entry这个接口中有这么多的方法,但是没有提供设置key的方法,因为它的底层是一颗搜索树,如果设置的key值,就要对这颗搜索树进行重新排序了,就乱了。
getKey方法:获取key值,返回key值。
getValue方法:获取value值,返回value值。
setValue方法:将key值中的value值换成自己设定的value值。
可以用Entry来输出容器中的键值对:
Set<Map.Entry<String,Integer>> set = treeMap.entrySet();
for (Map.Entry<String,Integer> entry : set) {
System.out.println("key: "+entry.getKey() + " value: "+entry.getValue());
}
注:1. Map和Set都是接口,不能直接实例化对象,要实例化对象得用hashMap或者更TreeMap类来实例化对象。
2. Map中存放的key值是唯一的,就像是TreeMap中,二叉搜索树左边是比根小的,右边是比根大的,根本就没有相同的节点的说法。
3. Map中key值不能进行修改,如果要修改只能是删了重新插入。
4. Map中的key值是可以分离出来存放到Set中的,Set这个容器就是Map改了一下源码然后实现的只能存放key值。
Set:是继承collection的接口类,里边只存放K的值。(key)
set中有这么多的方法,它的使用场景主要是对数据进行去重,因为key值是没有重复的。
(Map的使用场景主要是比如一个数据在当前数组中出现的次数,它需要用到value值来记录数组中每个数据元素出现的次数)
常用类有hashSet和TreeSet,Set中存放的key值一定是有序的。
如下图:给数据进行去重
public static void main7(String[] args) {
//给数据去重
int[] array = {1,3,4,5,3,5,1,2,8};
Set<Integer> set = new HashSet<>();
for (int i = 0; i < array.length; i++) {
set.add(array[i]);
}
System.out.println(set);
}
找到一个重复的数据:
public static void main8(String[] args) {
//找到第一个重复的数据 最好用接口引用一个类!!!
//因为它包含接口的方法,如果用一个集合类去引用只能使用当前类的方法
int[] array = {1,3,4,5,3,5,1,2,8};
Set<Integer> set = new HashSet<>();
for (int x : array) {
if (!set.contains(x)) {
set.add(x);
}else {
System.out.println(x);
return;
}
}
}
统计数组中的重复的数据: 可以用Set来实现,也可以用Map来实现,
Set实现就是看Set容器中有没有这个数据,如果没有就放进来,如果已经有这个数据了,就把容器中的这个数据删除。
Map实现就是如果没有这个数据,就放进来,value值设为1,如果有这个数据了,就子啊原来的value值基础上+1.最后遍历这个容器,只输出value值>1的数据。
public static int singleNumber1(int[] nums) {
//用Set,先遍历这个数组,如果没有这个元素,就放进来,如果没有就把这个元素删除
Set<Integer> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
if (!set.contains(nums[i])) {
set.add(nums[i]);
}else {
set.remove(nums[i]);
}
}
int val = set.hashCode();//为什么hashcode方法也是可以输出set中只有一个数据的情况
return val;
}
public static void main9(String[] args) {
//统计数组中 重复数据(val>=2)出现的次数?
//key是数组中的数据,value是key这个数据在数组中出现了几次
/*首先要清楚用哪一个容器来存储,Set容器只是存放了key值,Map容器存放了key值和value值
* 所以用Map容器*/
int[] array = {1,3,5,7,4,4,5,5,5,1};
Map<Integer,Integer> map = new HashMap<>();
for (int x : array) {//遍历数组
if (map.get(x) == null) {
//如果map这个容器中没有存放这个数据,就将value值设置为1
map.put(x,1);
}else { //如果有,就在原来的value值的基础上+1
//所以先看一下原来的这个value值是几,在原来的value值的基础上+1
int val = map.get(x);
map.put(x,val+1);
}
}
for (Map.Entry<Integer,Integer> entry : map.entrySet()) {
if (entry.getValue() > 1) {//如果重复的值的次数>1才输出它
System.out.println("key"+entry.getKey()+" value: "+entry.getValue());
}
}
//或者是用Map中的map.getOrDefault()方法
for (int x : array) {//默认值是0,在原来的基础上去更新+1
map.put(x,map.getOrDefault(x,0)+1);
}
}