文章目录
一、三大家族的构造方法:
1.Array家族
double[] arrayB = new double[] {2.0,3.0,5.6};
double[] arrayB = new double[10];
double[] arrayB = {2.0,3.0,5.6};
2.Collection家族
Collection家族有两个子类(两个t),一个是list,另一个是set
关于List:
ArrayList<Integer> listC = new ArrayList<>();
LinkedList<String> linked = new LinkedList<>();
关于Set:
HashSet<String> set = new HashSet<>();
LinkedHashSet<String> linked = new LinkedHashSet<>();
3.Map家族
Map家族和set家族有些像(HashSet--HashMap,LinkedHashSet---LinkedHashMap)
HashMap<String,Integer> map = new HashMap<>();
LinkedHashMap<String,String> linked = new LinkedHashMap<>();
1.Array家族
数组的创建:
用构造方法的:
double[] arrayB = new double[10];
double[] arrayB = new double[] {2.0,3.0,5.6};
直接创建的:
double[] arrayB = {2.0,3.0,5.6};
注意:
有几种数据类型你就可以创建几种数组,别见了`byte [] byteArray={97,98,99};`大惊小怪的
数组的样式是{2.0,3.0,5.6},只有你调用Arrays.toString(array2)才会得到[2.0,3.0,5.6]
问题:
比如你一开始创建了一个大小为3的int数组new Int[3],当你需要扩容的时候你必须new Int[4]然后使用for循环把原先数组的数据拷贝过去。
所以数组的问题就是长度必须指定而且一旦指定就不能修改。而且保存的数据必须是同一类型的元素。
2.Collection家族
3.关于List
有序有索引,所以索引就相当于它的键
java.util.List接口 extends Collection接口
List接口的特点:(有序+有索引+允许重复)
1.有序的集合,存储元素和取出元素的顺序是一致的(存储123 取出123)
2.有索引,包含了一些带索引的方法
3.允许存储重复的元素
ArrayList和LinkedList实现了List
ArrayList是数组,查询快增删慢
LinkedList是链表,查询慢增删快,因为是链表所以有大量操作首尾元素的方法
List的构造方法:
ArrayList和LinkedList实现了List,常使用多态:
List<String> list = new ArrayList<>();//多态
List<String> linked = new LinkedList<>();
List的样式是[a, b, itheima, d, a]
ArrayList构造方法:
ArrayList<Integer> listC = new ArrayList<>();
ArrayList的样式是[柳岩, 高圆圆, 赵又廷, 李小璐, 贾乃亮]
LinkedList构造方法
LinkedList<String> linked = new LinkedList<>();
LinkedList的样式是[www, a, b, c, com]
4.关于Set
java.util.Set接口 extends Collection接口
Set接口的特点:(无索引+不能重复)
1.不允许存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
实现了Set接口的:
java.util.HashSet集合 implements Set接口
HashSet特点:(无序+无索引+不能存储重复的元素)
1.不允许存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
4.底层是一个哈希表结构(查询的速度非常的快)
java.util.LinkedHashSet集合 extends HashSet集合
LinkedHashSet集合特点:(有序+无索引+不能重复)
底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序
Set的构造方法:
常使用多态:
Set<Integer> set = new HashSet<>();
使用set.add();添加元素后的格式为[a, b, c, d, a]
也可能是[Person[name="小美女",age=19],Person[name="小美女",age=18],Person[name="小美女",age=18]]
HashSet的构造方法:
HashSet<String> set = new HashSet<>();
使用set.add();添加元素后的格式为[a, b, c, d, a]
LinkedHashSet的构造方法
LinkedHashSet<String> linked = new LinkedHashSet<>();
使用set.add();添加元素后的格式为[a, b, c, d, a]
5.Map家族
java.util.Map<k,v>集合
Map集合的特点:
1.Map集合包含两个值(一个key,一个value),key和value是一一对应
实现了Map集合的接口:
java.util.HashMap<k,v>集合 implements Map<k,v>接口
HashMap集合的特点:(无序)
1.HashMap集合底层是哈希表:查询的速度特别的快
2.hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
实现了HashMap集合的接口:
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
LinkedHashMap的特点:(有序)
LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
Map的构造方法
构造方法常用多态:
Map<String,Integer> map = new HashMap<>();//多态
map.put()添加元素后{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}
HashMap的构造方法
HashMap<String,Integer> map = new HashMap<>();
map.put()添加元素后{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}
LinkedHashMap构造方法:
LinkedHashMap<String,String> linked = new LinkedHashMap<>();
linked.put()添加元素后{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}
HashTable构造方法
java.util.Hashtable<K,V>集合 implements Map<K,V>接口
HashMap集合(之前学的所有的集合):可以存储null值,null键
Hashtable集合,不能存储null值,null键
Hashtable<String,String> table = new Hashtable<>();
table.put()添加元素后{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}
二、of方法
适用于List接口,Set接口,Map接口的of方法
JDK9的新特性:
List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素
static <E> List<E> of(E... elements)
使用前提:
当集合中存储的元素的个数已经确定了,不在改变时使用
注意:
1.of方法只适用于List接口,Set接口,Map接口,不适用于这些接口的实现类
2.of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
3.Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常
构造方法:
List<String> list = List.of("a", "b", "a", "c", "d");//[a, b, a, c, d]
Set<String> set = Set.of("a", "b", "c", "d");//[a,b,c,d]
Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20);
//{王五=20, 李四=19, 张三=18}
三、三大家族的普通方法
1.Array家族
数组的创建:
double[] arrayB = new double[] {2.0,3.0,5.6};
double[] arrayB = new double[10];
double[] arrayB = {2.0,3.0,5.6};
数组方法的调用:
int[] array = { 5, 15, 30, 20, 10000, 30, 35 };
//array.lenth
int length = array.length;//7
//Arrays.toString(array)
Arrays.toString(array);//[5,15,30,20,10000,30,35]
Arrays.sort(array);//[5,15,20,30,30,35,10000]
//使用for (int i = 0; i < array.length; i++)遍历数组
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
//增强for循环遍历数组
int[] arr={1,2,3,4,5}
for(int i :arr){
System.out.println(i);
}
①增强for用来遍历数组 和 集合(set集合、list集合)
②itertor用来遍历集合(set集合、list集合)
③当然,你只需要记住数组的遍历方法一般就是for (int i = 0; i < array.length; i++) 和增强for ;集合的遍历方法一般就是itertor 和增强for;
④尽量不要用for (int i = 0; i < array.length; i++)遍历集合。集合可以转为数组toArray()然后使用for (int i = 0; i < array.length; i++)遍历,但是这么做是吃上屎了吗
2.Collection家族
构造方法:
使用多态:
Collection<String> coll = new ArrayList<>();
Collection<String> coll = new HashSet<>();
list子类的构造方法:
ArrayList<Integer> listC = new ArrayList<>();
LinkedList<String> linked = new LinkedList<>();
set子类的构造方法:
HashSet<String> set = new HashSet<>();
LinkedHashSet<String> linked = new LinkedHashSet<>();
普通方法:
java.util.Collection接口
所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法:
public boolean add(E e):把给定的对象添加到当前集合中 。返回值是一个boolean值,一般都返回true,所以不用接收,没有意义
public boolean remove(E e): 把给定的对象在当前集合中删除。返回值是一个boolean值,集合中存在元素,删除元素,返回true,集合中不存在元素,删除失败,返回false
public boolean contains(E e): 判断当前集合中是否包含给定的对象。
public boolean isEmpty(): 判断当前集合是否为空。
public int size(): 返回集合中元素的个数。
public Object[] toArray(): 把集合中的元素,存储到数组中。
public void clear() :清空集合中所有的元素。但是不删除集合,集合还存在。
//创建集合对象,可以使用多态
Collection<String> coll = new ArrayList<>();
Collection<String> coll = new HashSet<>();
//不管你创建的是ArrayList还是HashList,下面的方法都是通用的,因为我们学的是最顶层的接口Collection
System.out.println(coll);//输出为空而不是地址值,说明重写了toString方法
boolean b1 = coll.add("张三");
System.out.println("b1:"+b1);//b1:true
System.out.println(coll);//[张三]
coll.add("李四");
coll.add("李四");
coll.add("赵六");
coll.add("田七");
System.out.println(coll);//[张三, 李四, 赵六, 田七]
boolean b2 = coll.remove("赵六");
System.out.println("b2:"+b2);//b2:true
boolean b3 = coll.remove("赵四");
System.out.println("b3:"+b3);//b3:false
System.out.println(coll);//[张三, 李四, 田七]
boolean b4 = coll.contains("李四");
System.out.println("b4:"+b4);//b4:true
boolean b5 = coll.contains("赵四");
System.out.println("b5:"+b5);//b5:false
boolean b6 = coll.isEmpty();
System.out.println("b6:"+b6);//b6:false
int size = coll.size();
System.out.println("size:"+size);//size:3
Object[] arr = coll.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//public void clear() :清空集合中所有的元素。但是不删除集合,集合还存在
coll.clear();
System.out.println(coll);//[]
System.out.println(coll.isEmpty());//true
静态Static方法:
以下的方法都是先创一个Collection子类的列表,然后用Collection操作直接调用就可以
ArrayList<String> list = new ArrayList<>();//先创一个Collection子类的列表
Collections.addAll(list,"a","b","c","d","e");//Collection操作
Collections.shuffle(list);//Collection操作
Collections.sort(list01);//Collection操作
1.Collections.addAll()
和Collections.shuffle()
//往集合中添加多个元素的传统方法
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
ArrayList<String> list = new ArrayList<>();
//addAll()是collections的静态方法可以直接Collections.addAll来调用
Collections.addAll(list,"a","b","c","d","e");
System.out.println(list);//[a, b, c, d, e]
//打乱顺序:打乱集合顺序。
Collections.shuffle(list);
System.out.println(list);//[b, d, c, a, e]
2.Collections.sort()
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(3);
list01.add(2);
System.out.println(list01);//[1, 3, 2]
//public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
Collections.sort(list01);//默认是升序
3.Collections.sort()
来自定义排序
Collections.sort()来自定义排序前提:
被排序的集合里边存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序的规则
public class Person implements Comparable<Person>{.....}
Comparable接口的排序规则:
用自己(this)减去参数就是升序(自己在前面,就是升),
参数减去自己(this)就是降序(自己在后面,就是降)
public class Person implements Comparable<Person>{
...........
//重写排序的规则
@Override
public int compareTo(Person o) {
//自定义比较的规则,比较两个人的年龄(this,参数Person)
//return this.getAge() - o.getAge();//用自己(this)减去参数就是升序,年龄升序排序
return o.getAge() - this.getAge();//年龄降序排序
}
}
public class Demo02Sort {
public static void main(String[] args) {
ArrayList<Person> list03 = new ArrayList<>();
list03.add(new Person("张三",18));
list03.add(new Person("李四",20));
list03.add(new Person("王五",15));
Collections.sort(list03);
System.out.println(list03);//[ Person{name='王五', age=15},Person{name='张三', age=18}, Person{name='李四', age=20}]
}
}
3.Collections.sort(List<T> list,Comparator<? super T> )
- java.utils.Collections是集合工具类,用来对集合进行操作。部分方法如下:
public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。
Comparator和Comparable的区别
Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较的规则compareTo方法
Comparator:相当于找一个第三方的裁判,比较两个
Comparator的排序规则:
o1-o2:升序
public class Demo03Sort {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(3);
list01.add(2);
System.out.println(list01);//[1, 3, 2]
Collections.sort(list01, new Comparator<Integer>() {
//重写比较的规则
@Override
public int compare(Integer o1, Integer o2) {
//return o1-o2;//升序
return o2-o1;//降序
}
});
System.out.println(list01);
ArrayList<Student> list02 = new ArrayList<>();
list02.add(new Student("a迪丽热巴",18));
list02.add(new Student("古力娜扎",20));
list02.add(new Student("杨幂",17));
list02.add(new Student("b杨幂",18));
System.out.println(list02);
Collections.sort(list02, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//按照年龄升序排序
return o1.getAge()-o2.getAge();
}
});
System.out.println(list02);
}
}
3.关于List
List和set是Collection的子类,它们有有一些独特的方法,所以我们必须单独拿出来说一说
List的构造方法:
List<String> list = new ArrayList<>();//多态
List的普通方法:
List接口中带索引的方法(特有)
- public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
- public E get(int index):返回集合中指定位置的元素。
- public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
- public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
//创建一个List集合对象
List<String> list = new ArrayList<>();//多态
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("a");
//打印集合[a, b, c, d, a]
list.add(3,"itheima");//在c和d之间添加一个itheima现在是[a, b, c, itheima, d, a]
String removeE = list.remove(2);//返回值是c
//现在的集合是[a, b, itheima, d, a]
String setE = list.set(4, "A");//把最后一个a,替换为A
System.out.println("被替换的元素:"+setE);//被替换的元素:a
//现在的集合是[a, b, itheima, d, A]
//List集合遍历有3种方式
//使用普通的for循环(相当不提倡!!!)
for(int i=0; i<list.size(); i++){
String s = list.get(i);//public E get(int index):返回集合中指定位置的元素。
System.out.println(s);
}
System.out.println("-----------------");
//使用迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("-----------------");
//使用增强for
for (String s : list) {
System.out.println(s);
}
①增强for用来遍历数组 和 集合(set集合、list集合)
②itertor用来遍历集合(set集合、list集合)
③当然,你只需要记住数组的遍历方法一般就是for (int i = 0; i < array.length; i++) 和增强for ;集合的遍历方法一般就是itertor 和增强for;
④尽量不要用for (int i = 0; i < array.length; i++)遍历list或set集合。集合可以转为数组toArray()然后使用for (int i = 0; i < array.length; i++)遍历,但是这么做是吃上屎了吗
4.关于ArrayList
ArrayList虽然是Lsit的子类,它有一些独特的方法,所以我们必须单独拿出来说一说
普通方法:
public boolean add(E e):向集合当中添加元素,参数的类型和泛型一致。返回值代表添加是否成功。
//boolean success = list.add("柳岩");//True
public E get(int index):从集合当中获取元素,参数是索引编号,返回值就是对应位置的元素。
public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素。
public int size():获取集合的尺寸长度,返回值是集合中包含的元素个数。
ArrayList<String> list = new ArrayList<>();
list.add("柳岩");
list.add("高圆圆");
list.add("赵又廷");
list.add("李小璐");
list.add("贾乃亮");
System.out.println(list); // [柳岩, 高圆圆, 赵又廷, 李小璐, 贾乃亮]
String name = list.get(2);// 赵又廷
String whoRemoved = list.remove(3);// 李小璐
System.out.println(list); // [柳岩, 高圆圆, 赵又廷, 贾乃亮]
int size = list.size();//4
5.关于LinkedList
LinkedList虽然是Lsit的子类,它有一些独特的方法,所以我们必须拿出来说一说
普通方法
java.util.LinkedList集合 implements List接口
LinkedList集合里边包含了大量操作首尾元素的方法:
- public void addFirst(E e):将指定元素插入此列表的开头。
- public void addLast(E e):将指定元素添加到此列表的结尾。
- public void push(E e):将元素推入此列表所表示的堆栈。
- public E getFirst():返回此列表的第一个元素。
- public E getLast():返回此列表的最后一个元素。
- public E removeFirst():移除并返回此列表的第一个元素。
- public E removeLast():移除并返回此列表的最后一个元素。
- public E pop():从此列表所表示的堆栈处弹出一个元素。
- public boolean isEmpty():如果列表不包含元素,则返回true。
(以上是LinkedList集合特有的方法,不能使用多态来使用这些方法)
LinkedList<String> linked = new LinkedList<>();
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println(linked);//[a, b, c]
linked.addFirst("www");//[www, a, b, c]
//linked.push("www"); //和上一步等价
linked.addLast("com");
System.out.println(linked);//[www, a, b, c, com]
//linked.clear();//清空集合中的元素
//public boolean isEmpty():如果列表不包含元素,则返回true。
if(!linked.isEmpty()){
String first = linked.getFirst();
System.out.println(first);
String last = linked.getLast();
System.out.println(last);
String first = linked.removeFirst();
//String first = linked.pop(); 和上一步等价
System.out.println("被移除的第一个元素:"+first);
String last = linked.removeLast();
System.out.println("被移除的最后一个元素:"+last);
6.关于Set
Set集合 和 它的两个子类(HashSet与LinkedHashSet)继承了Collection,并没有自己特殊的什么方法,多半是继承Collection的方法
HashSet的普通方法:
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(3);
set.add(2);
set.add(1);
//使用迭代器遍历set集合
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer n = it.next();
System.out.println(n);//1,2,3
}
//使用增强for遍历set集合
System.out.println("-----------------");
for (Integer i : set) {
System.out.println(i);
}
LinkedHashSet的普通方法
public class Demo04LinkedHashSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("www");
set.add("abc");
set.add("abc");
set.add("itcast");
System.out.println(set);//[abc, www, itcast] 无序,不允许重复
LinkedHashSet<String> linked = new LinkedHashSet<>();
linked.add("www");
linked.add("abc");
linked.add("abc");
linked.add("itcast");
System.out.println(linked);//[www, abc, itcast] 有序,不允许重复
}
}
7.Map家族
构造方法:
构造方法常用多态:
Map<String,Integer> map = new HashMap<>();//多态
map的普通方法1:
public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。返回值没有意义
public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
public V remove(Object key): 指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
返回值:V key存在,v返回被删除的值 key不存在,v返回null
boolean containsKey(Object key) 判断集合中是否包含指定的键。包含返回true,不包含返回false
Map<String,Integer> map = new HashMap<>();//多态
map.put("赵丽颖",168);
map.put("杨颖",165);
map.put("林志玲",178);
System.out.println(map);//{林志玲=178, 赵丽颖=168, 杨颖=165}
Integer v1 = map.get("杨颖");
System.out.println("v1:"+v1);//v1:165
Integer v1 = map.remove("林志玲");
System.out.println("v1:"+v1);//v1:178
System.out.println(map);//{赵丽颖=168, 杨颖=165}
boolean b1 = map.containsKey("赵丽颖");
System.out.println("b1:"+b1);//b1:true
map的普通方法2:
既然是map的普通方法,调用方式就是 map.keySet();
Set<K> keySet() 返回此映射中包含的键的 Set 视图。
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖",168);
map.put("杨颖",165);
map.put("林志玲",178);
Set<String> set = map.keySet();//key是字符串类型,set集合也是字符串类型
//使用迭代器遍历Set集合
Iterator<String> it = set.iterator();
while (it.hasNext()){
String key = it.next();
//3.通过Map集合中的方法get(key),通过key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
//使用增强for遍历Set集合
for(String key : set){
//3.通过Map集合中的方法get(key),通过key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
//使用增强for遍历Set集合
for(String key : map.keySet()){
//3.通过Map集合中的方法get(key),通过key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
map的普通方法3:
既然是map的普通方法,调用方式就是 map.entrySet();
Set<Map.Entry<K,V>> entrySet() 方法名entrySet(),是返回值是Set<Map.Entry<K,V>>。
entry.getKey()获取键
entry.getValue()获取值
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖",168);
map.put("杨颖",165);
map.put("林志玲",178);
Set<Map.Entry<String, Integer>> set = map.entrySet();
//使用迭代器遍历Set集合
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Integer> entry = it.next();
//3.使用Entry对象中的方法getKey()和getValue()获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
//使用增强for遍历
for(Map.Entry<String,Integer> entry:set){
//3.使用Entry对象中的方法getKey()和getValue()获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
8.关于LinkedHashMap
public class Demo01LinkedHashMap {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("a","a");
map.put("c","c");
map.put("b","b");
map.put("a","d");
System.out.println(map);// key不允许重复,无序 {a=d, b=b, c=c}
LinkedHashMap<String,String> linked = new LinkedHashMap<>();
linked.put("a","a");
linked.put("c","c");
linked.put("b","b");
linked.put("a","d");
System.out.println(linked);//{a=d, c=c, b=b} key不允许重复,有序,存和取的顺序是一致的。
}
}
9.关于Hashtable
java.util.Hashtable<K,V>集合 implements Map<K,V>接口
Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
HashMap集合(之前学的所有的集合):可以存储null值,null键
Hashtable集合,不能存储null值,null键
Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
Hashtable的子类Properties依然活跃在历史舞台
Properties集合是一个唯一和IO流相结合的集合
具体使用:
public class Demo02Hashtable {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put(null,"a");
map.put("b",null);
map.put(null,null);
System.out.println(map);//{null=null, b=null}
Hashtable<String,String> table = new Hashtable<>();
table.put(null,"a");//NullPointerException
table.put("b",null);//NullPointerException
table.put(null,null);//NullPointerException
}
}