.
1、HashSet
1、Set是无序、不包含重复元素、可以存放null值的Collection,
2、当Set的泛型引用自定义的类时,自定类中需要重写toString()、hashcode()、equals()三个方法才能表现set不可重复性的特性
package cn.tedu.set;
/*本类用于测试set接口*/
import java.util.HashSet;
import java.util.Set;
public class TestSet {
public static void main(String[] args) {
Set<String> set=new HashSet<>();
/*无序、不能重复、可以存放null值*/
set.add("牛气冲天");
set.add("虎虎生威");
set.add("虎虎生威");
set.add(null);
set.add("null");
System.out.println(set);
System.out.println("===================");
/*Set集合如果要定义自己写的泛型类,那么定义的类需要重写toString、hashCode()、equals才能实现set的不重复特性*/
Set<Studnet> set2=new HashSet<>();
Studnet s1 = new Studnet("张三", 3);
Studnet s2 = new Studnet("李四", 4);
Studnet s3 = new Studnet("李四", 4);
set2.add(s1);
set2.add(s2);
set2.add(s3);
System.out.println(set2);
}
}
2、HashMap
2.1、特点
1、HashMap底层结构:数组+链表(链表长度小于6时)
数组+红黑树(链表的长度大于8时)
2、HashMap实际上是存放一个个Entry(k,v);
3、Map的初始容量是16,默认的加载因子是0.75f(当存放16*0.75个数组时就会扩容),约等于2倍扩容注意会发生rehash
4、map中当键key相同时value值会覆盖之前的;
5、当存放数据时,会根据hash算法来计算数据的存放位置,算法:hash(key)%n , n就是数组的长度,其实也就是集合的容量
2.2、常用方法
package cn.tedu.map;
/*本类用于测试map接口*/
import java.util.*;
public class TestMap {
public static void main(String[] args) {
/*1.Map中的数据要符合映射规则,一定注意要同时指定K和V的数据类型*/
Map<Integer,String> map=new HashMap<>();
/*2.map集合存放数据的方法时put(),需要同时赋值k和v*/
map.put(9527,"白骨精");
map.put(9528,"黑熊精");
map.put(9529,"鲤鱼精");
map.put(9530,"黄毛怪");
map.put(9531,"黑熊精");
map.put(9527,"爱莎公主");
/*1、map中存放的都是无序的数据
2、map中的value值可以重复
3、map中的key值不能重复,不然之前的value值会被覆盖*/
System.out.println(map);
// map.clear();
System.out.println(map.hashCode());
System.out.println(map.equals("黄毛怪"));
System.out.println(map.isEmpty());
System.out.println(map.size());
System.out.println(map.containsKey(9527));//判断map集合中是否存在指定的键key
System.out.println(map.containsValue("白骨精"));//判断map集合中是否存在指定的值value
System.out.println(map.get(9527));//根据key获取对应的value值
System.out.println(map.remove(9529));//删除此key值对应的键值对
System.out.println(map.containsKey(9529));
Collection<String> values = map.values();//把map中的值取出来放在一个Collection集合中
System.out.println(values);
}
}
2.3、两种迭代方式
.
map集合没有迭代器,需要借助Set里的iterator迭代器
方式一:Set keySet = map.keySet();
方式二:Set<Map.Entry<Integer, String>> entries = map.entrySet();
package cn.tedu.map;
import java.util.*;
public class test {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap<>();
map.put(9527,"白骨精");
map.put(9528,"黑熊精");
map.put(9529,"鲤鱼精");
map.put(9530,"黄毛怪");
map.put(9531,"黑熊精");
map.put(9527,"爱莎公主");
//map集合的迭代方式 map本身没有迭代器,需要先转换为set集合
/*方式一(keySet()):Set<key>把map的所有key值存到set集合中*/
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while (it.hasNext()){
Integer key = it.next();
String value = map.get(key);
System.out.println("{"+key+","+value+"}");
}
/*方式二(entrySet):把map中的一个键值对key&value作为一个Entry<k,v>整体放入set
* 一对K,V就是一个Entry*/
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
while (iterator.hasNext()){
Map.Entry<Integer, String> entry = iterator.next();
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println("{"+key+","+value+"}");
}
}
}
2.4、利用HashMap统计字符串中字符
注意:引用类型的初始值都是null哦!
package cn.tedu.map;
/*本类用于字符串中字符个数统计案例*/
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class TestMap2 {
public static void main(String[] args) {
System.out.println("请您输入域要统计的字符串:");
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
/*统计的是每个字母出现的次数,单个字符是char,对应的包装类是Character
* Integer统计的是这个字母出现的次数,可以重复,所以放在value位置*/
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < input.length(); i++) {
char key = input.charAt(i);//获取字符串指定下标处的值
Integer value = map.get(key);
if (value==null){
map.put(key,1);
}else {
map.put(key,value+1);
}
}
System.out.println(map);
}
}
3、拓展
HashMap扩容
成长因子:
static final float DEFAULT_LOAD_FACTOR = 0.75f;
前面的讲述已经发现,当你空间只有仅仅为10的时候是很容易造成2个对象的hashcode 所对应的地址是一个位置的情况。这样就造成 2个 对象会形成散列桶(链表)。这时就有一个加载因子的参数,值默认为0.75 ,如果你hashmap的 空间有 100那么当你插入了75个元素的时候 hashmap就需要扩容了,不然的话会形成很长的散列桶结构,对于查询和插入都会增加时间,因为它要一个一个的equals比较。但又不能让加载因子很小,如0.01,这样显然是不合适的,频繁扩容会大大消耗你的内存。这时就存在着一个平衡,jdk中默认是0.75,当然负载因子可以根据自己的实际情况进行调整。