学习Collection接口中的方法即可
创建包: cn.tedu.collection
创建类: TestSet.java
package cn.tedu.collection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**这个类用来测试Set接口的方法*/
public class TestSet {
public static void main(String[] args) {
//1.创建对象
//Set s = new Set();//报错,Set是接口,接口不可以实例化,也就是创建对象
Set<String> set = new HashSet<String>();
//2.set集合数据存放测试
set.add("牛气冲天");//向set集合添加数据
set.add("牛气冲天");//向set集合添加重复的数据
set.add("牛气冲天");//向set集合添加重复的数据
set.add("虎虎生威");//向set集合添加数据
//set.add("null");//向set集合添加字符串类型的null数据
set.add(null);//向set集合添加数据null
/**总结1:set集合中的元素都是无序的*/
/**总结2:set集合中的元素不能重复*/
/**总结3:set集合中可以存放null元素,也只允许存放0-1个*/
System.out.println(set);//查看set集合中的元素
//3.set集合常用方法测试
//set.clear();//清空Set集合
System.out.println(set.contains("小兔纸"));//false,判断set集合中是否包含指定元素"小兔纸"
System.out.println(set.equals("牛气冲天"));//false,判断set集合对象与指定元素是否相等
System.out.println(set.hashCode());//1961052313,获取当前set集合对象的哈希码
System.out.println(set.isEmpty());//false,判断当前集合是否为空
System.out.println(set.remove("null"));//false,移除指定元素,没有"null"元素,所以返回false
System.out.println(set.remove(null));//true,成功移除指定元素null,所以返回true
System.out.println(set);
System.out.println(set.size());//2,获取当前set集合的元素个数,类似数组长度
Object[] array = set.toArray();//把集合中的元素放入数组中
System.out.println(Arrays.toString(array));//使用数组工具类查看数组中的元素
//4.集合间的操作
Set<String> set2 = new HashSet();
set2.add("小老鼠");//给set2集合添加指定元素
set2.add("小牛犊");//给set2集合添加指定元素
set2.add("小脑斧");//给set2集合添加指定元素
set2.add("小兔纸");//给set2集合添加指定元素
System.out.println(set2);//查看set2集合中的元素
System.out.println(set.addAll(set2));//true,把集合set2中的元素添加到set集合中,成功返回true
System.out.println(set.containsAll(set2));//true,判断set集合中是否包含set2集合中的所有元素,如果包含返回true
System.out.println(set.removeAll(set2));//ture,移除set集合中属于set2集合的所有元素
System.out.println(set.containsAll(set2));//false,判断set集合中是否包含set2集合中的所有元素,不包含返回false
System.out.println(set.retainAll(set2));
/**retainAll()方法是取两个集合直接的公共部分,谁调用,影响谁*/
// set.add("小海滕");
// set2.add("小海滕");
// System.out.println(set.retainAll(set));//set没变
// System.out.println(set.retainAll(set2));//set剩set与set2的交集
// System.out.println(set2.retainAll(set));//set2剩set2与set的交集
// System.out.println(set);
// System.out.println(set2);
//5.集合的迭代
Iterator<String> it = set2.iterator();//5.1获取集合的迭代器
while(it.hasNext()) {
//5.2判断集合是否有下个元素
String s = it.next();//5.3如果有,进循环获取当前遍历到的元素
System.out.println(s);
}
}
}
底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K存入内部的HashMap中,其中K不允许重复,允许使用null.
创建包: cn.tedu.collection
创建类: TestHashSet2.java
package cn.tedu.collection;
import java.util.HashSet;
import java.util.Iterator;
/**本类用于测试HashSet的用法*/
public class TestHashSet2 {
public static void main(String[] args) {
//1.创建HashSet对象
HashSet<Integer> set = new HashSet();
//2.向HashSet集合添加元素
set.add(100);
set.add(200);
set.add(300);
set.add(200);
set.add(200);
/**总结1:HashSet中的元素没有顺序,且不允许重复*/
System.out.println(set);
//3.测试常用方法
//set.clear();//清空set集合
System.out.println(set.contains(200));//true,判断集合是否包含指定元素
System.out.println(set.isEmpty());//false,判断集合是否为空
System.out.println(set.remove(100));//true,移除集合中的指定元素
System.out.println(set.size());
//4.迭代set集合
Iterator<Integer> it = set.iterator();//获取集合的迭代器用来遍历
while(it.hasNext()) {
//判断集合中是否有下一个元素,没有则跳出循环
Integer num = it.next();//获取当前遍历到的元素
System.out.println(num);//打印当前遍历到的元素
}
}
}
Java.util接口Map
类型参数 : K - 表示此映射所维护的键 V – 表示此映射所维护的对应的值
也叫做哈希表、散列表. 常用于键值对结构的数据.其中键不能重复,值可以重复
TIPS:源码摘抄:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
初始容量1<<4,相当于1*(2^4),也就是16
static final float DEFAULT_LOAD_FACTOR = 0.75f;
默认的加载因子是0.75f,也就是存到75%开始扩容,按照2的次幂进行扩容
学习Collection接口中的方法即可
void clear() 从此映射中移除所有映射关系(可选操作) boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true
Set> entrySet() 返回此映射中包含的映射关系的 Set 视图
boolean equals(Object o) 比较指定的对象与此映射是否相等
V get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null
int hashCode() 返回此映射的哈希码值
boolean isEmpty() 如果此映射未包含键-值映射关系,则返回 true
Set keySet() 返回此映射中包含的键的 Set 视图
V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)
void putAll(Map extends K,? extends V> m)从指定映射中将所有映射关系复制到此映射中(可选操作)
V remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)
int size() 返回此映射中的键-值映射关系数
Collection values() 返回此映射中包含的值的 Collection 视图
创建包: cn.tedu.collection
创建类: TestMap.java
package cn.tedu.collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**本类用于测试Map接口*/
public class TestMap {
public static void main(String[] args) {
//1.创建Map对象
//map中的数据要符合映射规则,一定注意要同时指定K和V的数据类型
//至于K和V需要指定成什么类型的数据,取决于你的具体需求
Map<Integer,String> map = new HashMap();//注意导包:java.util
//2.常用方法测试
//添加数据,需要同时指定K和V
map.put(9527, "白骨精");//向map集合添加数据
map.put(9528, "黑熊精");//向map集合添加数据
map.put(9528, "唐三藏");
map.put(9529, "者行孙");
/**
* 总结1:Map存放的都是无序数据
* 总结2:Map中的key不可以重复,如果重复,此Key对应的值会被覆盖
*map打印结果: {9527=白骨精, 9528=唐三藏, 9529=者行孙}
*/
//查看map集合中的元素
System.out.println(map);
//map.clear();//清空map集合
System.out.println(map.containsKey(9527));//true,判断当前map集合是否包含指定的key
System.out.println(map.containsValue("土地老儿"));//false,判断当前map集合是否包含指定的value
System.out.println(map.equals("者行孙"));//false,判断"者行孙"与map是否相等
System.out.println(map.get(9529));//者行孙,根据对应的key来获取对应的value
System.out.println(map.hashCode());//84598429,获取当前map集合的哈希码
System.out.println(map.isEmpty());//false,判断当前map集合是否为空
System.out.println(map.remove(9529));//者行孙,删除map中key对应的value,正确删除后返回被删除元素
System.out.println(map.get(9529));//null,没有拿到任何元素,根据指定的key获取对应value
System.out.println(map.size());//2,获取集合中元素的个数
Collection<String> values = map.values();//把map中的所有value收集起来放到collection中
System.out.println(values);//[白骨精, 唐三藏]
}
}
创建包: cn.tedu.collection
创建类: TestMap.java
package cn.tedu.collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**本类用于测试Map接口*/
public class TestMap {
public static void main(String[] args) {
//1.创建Map对象
//map中的数据要符合映射规则,一定注意要同时指定K和V的数据类型
//至于K和V需要指定成什么类型的数据,取决于你的具体需求
Map<Integer,String> map = new HashMap();//注意导包:java.util
//2.常用方法测试
//添加数据,需要同时指定K和V
map.put(9527, "白骨精");//向map集合添加数据
map.put(9528, "黑熊精");//向map集合添加数据
map.put(9528, "唐三藏");
map.put(9529, "者行孙");
/**
* 总结1:Map存放的都是无序数据
* 总结2:Map中的key不可以重复,如果重复,此Key对应的值会被覆盖
*map打印结果: {9527=白骨精, 9528=唐三藏, 9529=者行孙}
*/
//查看map集合中的元素
System.out.println(map);
//map.clear();//清空map集合
System.out.println(map.containsKey(9527));//true,判断当前map集合是否包含指定的key
System.out.println(map.containsValue("土地老儿"));//false,判断当前map集合是否包含指定的value
System.out.println(map.equals("者行孙"));//false,判断"者行孙"与map是否相等
System.out.println(map.get(9529));//者行孙,根据对应的key来获取对应的value
System.out.println(map.hashCode());//84598429,获取当前map集合的哈希码
System.out.println(map.isEmpty());//false,判断当前map集合是否为空
System.out.println(map.remove(9529));//者行孙,删除map中key对应的value,正确删除后返回被删除元素
System.out.println(map.get(9529));//null,没有拿到任何元素,根据指定的key获取对应value
System.out.println(map.size());//2,获取集合中元素的个数
Collection<String> values = map.values();//把map中的所有value收集起来放到collection中
System.out.println(values);//[白骨精, 唐三藏]
//对map集合进行迭代
/**方式一
* 遍历map中的数据,需要把map集合转换成set集合
* Set keySet() : 把map集合中的所有的key存到set集合中
* */
Set<Integer> keySet = map.keySet();
//想要遍历set集合,需要先拿到集合的迭代器对象
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()) {
//判断集合中是否有下个元素,如果有,继续迭代,如果没有,跳出循环
Integer key = it.next();//依次获取/set集合中的每一个key
String value = map.get(key);//通过key获取对应的value
System.out.println("{" + key + "," + value + "}");
}
/**方式二
* 遍历map中的数据,需要把map集合转换成set集合
* Set> entrySet() : 把map集合中的一组key&value数据整体放入set中
* 一对儿 K,V 是一个Entry
*/
Set<Entry<Integer, String>> entrySet = map.entrySet();
//遍历set集合,得到每个Entry对象
//获取此set集合对应的迭代器对象it2
Iterator<Entry<Integer, String>> it2 = entrySet.iterator();
while(it2.hasNext()) {
Entry<Integer, String> entry = it2.next();
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println("[" + key + ":" + value + "]");
}
}
}
HashMap的键要同时重写hashCode()和equlas()
hashCode()用来判定二者的hash值是否相同,重写后根据属性生成
equlas()用来判断属性的值是否相同,重写后,根据属性判断
–equlas()判断数据如果相等,hashCode()必须相同
–equlas()判断数据如果不等,hashCode()尽量不同
HashMap底层是一个Entry[ ]数组,当存放数据时,会根据hash算法来计算数据的存放位置
算法:hash(key)%n , n就是数组的长度,其实也就是集合的容量
当计算的位置没有数据的时候,会直接存放数据
当计算的位置,有数据时,会发生hash冲突/hash碰撞,解决的办法就是采用链表的结构,在对应的数据位置存放链表的头节点,对于这个链表来说,每次新加的节点会从头部位置开始加入,也就是说,数组中的永远是新节点.
创建包: cn.tedu.collection
创建类: TestHashMap.java
package cn.tedu.collection;
import java.util.HashMap;
/**本类用于HashMap的练习*/
public class TestHashMap {
public static void main(String[] args) {
//创建HashMap对象
HashMap<Integer,String> map = new HashMap();
/**
* 源码摘抄:
* static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
* 初始容量为1<<4,相当于1*(2^4)=16
* static final float DEFAULT_LOAD_FACTOR = 0.75f;
* 默认的加载因子是0.75,也就是说存到75%开始扩容,按照2的次幂进行扩容
*/
/*
* 达到容量的加载因子后,就会重新开辟空间,重新计算所有对象的存储位置,也叫做rehash
* 设置初始容量与加载因子要讲求相对平衡,如果加载因子过低,则rehash过于频繁,影响性能
* 如果初始容量设置太高或者加载因子设置太高,影响查询效率
*/
}
}
创建包: cn.tedu.collection
创建类: TestMap2.java
package cn.tedu.collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* 本类用来完成Map集合相关练习
* 需求:提示并接收用户输入的一串字符,并且统计出每个字符出现的次数
* */
public class TestMap2 {
public static void main(String[] args) {
//1.提示用户输入要统计的字符串
System.out.println("请输入您要统计的字符串");
//2.接收用户输入的要统计的字符串
String input = new Scanner(System.in).nextLine();
//3.获取到用户输入的每个字符,String底层维护的是char[]
//创建map集合存放数据,格式:{b=2,d=4,g=3}
/**统计的是每个字符出现的次数,所以字符是char类型,次数是int,但是不可以使用基本类型,需要使用包装类型*/
Map<Character,Integer> map = new HashMap();
//开始位置:0 - 数组的第一个元素
//结束位置:
//如何变化:++
for (int i = 0; i < input.length(); i++) {
char key = input.charAt(i);//获取一串字符中指定位置上的字符
System.out.println("获取到的第"+(i+1)+"个字符:"+key);
//4.统计每个字符出现的个数,存起来,存到map
Integer value = map.get(key);//要先拿着key到map中找是不是有value
if(value == null) {
//如果判断为null,说明之前没有存过这个字符
map.put(key, 1);//把当前的字符作为key存入,次数存1
}else {
map.put(key,value+1);//如果存过值,给之前的次数+1
}
}
System.out.println("各个字符出现的频率为:");
System.out.println(map);
}
}
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,当然负载因子可以根据自己的实际情况进行调整。