Set
Set集合概述和特点
Set集合特点:
不包含重复元素的集合
没有带索引的方法,所以不能使用普通for循环遍历
import java.util.HashSet;
import java.util.Set;
public class day1Set集合概述和特点 {
public static void main(String[] args) {
//创建集合对象
Set<String> set = new HashSet<>();
//添加元素
set.add("hello");
set.add("world");
set.add("java");
//不包含重复元素
set.add("world");
//遍历
for (String s : set){
System.out.println(s);
}
}
}
哈希值:
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
public int hashCode();返回对象的哈希码值
public class day2哈希值 {
public static void main(String[] args) {
//创建学生对象
day2Student s1 = new day2Student("林青霞",30);
//同一个对象多次调用hashCode()这个方法返回的哈希值是相同的
System.out.println(s1.hashCode());//1956725890
System.out.println(s1.hashCode());//1956725890
System.out.println("---------------------------");
//默认情况下,不同对象的哈希值是不相同的
//通过方法重写,可以实现不同对象的哈希值是相同的
day2Student s2 = new day2Student("林青霞",30);
System.out.println(s2.hashCode());//356573597
System.out.println("-------------------------");
System.out.println("hello".hashCode());//99162322
System.out.println("world".hashCode());//113318802
System.out.println("java".hashCode());//3254818
System.out.println("world".hashCode());//113318802
System.out.println("重地".hashCode());//1179395
System.out.println("通话".hashCode());//1179395
}
}
HashSet集合概述和特点
底层数据结构是哈希表
对集合的迭代顺序不保证,也就是说不保证存储和取出的元素顺序一致
没有带索引的方法,所以不能使用普通for循环遍历
由于是set集合,所以是不包含重复元素的集合
import java.util.HashSet;
public class day3HashSet集合概述和特点 {
public static void main(String[] args) {
//创建集合对象
HashSet<String> hs = new HashSet<>();
//添加元素
hs.add("hello");
hs.add("world");
hs.add("java");
hs.add("world");
//遍历
for (String s : hs){
System.out.println(s);
}
}
}
HashSet集合保证元素唯一性源码分析
//创建集合对象
HashSet<String> hs = new HashSet<>();
//添加元素
hs.add("hello");
hs.add("world");
hs.add("java");
------------------------------------
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
publi c V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果哈希表未初始化,就对其进行初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//根据对象的哈希值计算对象的存储位置,如果该位置没有元素,就存储元素
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
/*
存入的元素和以前的元素比较哈希值
如果哈希值不同,会继续向下执行,把元素添加到集合
如果哈希值相同,会调用对象的equals()方法比较
如果返回false,会继续向下执行,把元素添加到集合
如果返回true,说明元素重复,不存储
*/
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
哈希表
JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
JDK8之后,在长度比较长的时候,底层实现了优化
//需求:创建一个存储学生对象的系统,存储多个学生对象,使用程序实现在控制台遍历
//要求:学生对象的成员变量相同,我们就认为是同一个对象
//
//思路:
//1.定义学生类
//2.创建HashSet集合对象
//3.创建学生对象
//4.把学生添加到集合
//5.遍历集合(加强for循环)
//6.在学生类中重写两个方法 hashcode()和equals() 自动生成即可 alt+insert
import java.util.HashSet;
public class day6HashSet集合存储学生对象并遍历 {
public static void main(String[] args) {
//创建hashset集合对象
HashSet<day6Student> hs = new HashSet<>();
//创建学生对象
day6Student s1 = new day6Student("林青霞",30);
day6Student s2 = new day6Student("张曼玉",35);
day6Student s3 = new day6Student("王祖贤",33);
day6Student s4 = new day6Student("王祖贤",33);
//把学生添加到集合
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
//遍历集合
for (day6Student s : hs){
System.out.println(s.getName()+","+s.getAge());
}
}
}
package 集合框架.Set;
import java.util.Objects;
public class day6Student {
private String name;
private int age;
public day6Student(){
}
public day6Student(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
day6Student that = (day6Student) o;
return age == that.age && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
//LinkedHashSet集合特点
//1.哈希表和链表实现的Set接口,具有可预测的迭代次序
//2.由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
//3.由哈希表保证元素唯一,也就是说没有重复的元素
//
//练习:存储字符串并遍历
import java.util.LinkedHashSet;
public class day7LinkedHashSet集合概述和特点 {
public static void main(String[] args) {
//创建集合对象
LinkedHashSet<String> lsk = new LinkedHashSet<>();
//添加元素
lsk.add("hello");
lsk.add("world");
lsk.add("java");
lsk.add("world");
//遍历集合
for (String s : lsk){
System.out.println(s);
}
}
}
TreeSet集合概述和特点
1.元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet():根据其元素的自然顺序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
2.没有带索引的方法,所以不能使用普通for循环进行遍历
3.由于是set集合,所以不包含重复元素的集合
TreeSet集合练习:存储整数并遍历
import java.util.TreeSet;
public class day8TreeSet集合概述和特点 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Integer> ts = new TreeSet<>(); //所有基本类型引用时需要用包装类
//添加元素
ts.add(10);
ts.add(40);
ts.add(30);
ts.add(50);
ts.add(20);
ts.add(30);
//遍历
for (Integer i : ts){
System.out.println(i);
}
}
}
自然排序Comparabale的使用
存储学生对象并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大进行排序,年龄相同时,按照姓名的字母顺序排序
import java.util.TreeSet;
public class day9自然排序Comparabale的使用 {
public static void main(String[] args) {
//创建集合对象
TreeSet<day9Student> ts = new TreeSet<>();
//创建学生对象
day9Student s1 = new day9Student("xishi",29);
day9Student s2 = new day9Student("wangzhaojun",28);
day9Student s3 = new day9Student("diaochan",30);
day9Student s4 = new day9Student("yangyuhuan",33);
day9Student s5 = new day9Student("linqingxia",33);
day9Student s6 = new day9Student("linqingxia",33);
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//遍历集合
for (day9Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
}
}
package 集合框架.Set;
public class day9Student implements Comparable<day9Student>{
private String name;
private int age;
public day9Student(){
}
public day9Student(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(day9Student s) {
// return 0;
// return 1;
// return -1;
//按照年龄进行排序
// int num = s.age - this.age; 升序
int num = this.age - s.age;
int num2 = num==0?this.name.compareTo(s.name):num;
return num2;
}
}
比较器排序Comparator的使用
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
import java.util.Comparator;
import java.util.TreeSet;
public class day10比较器排序Comparator的使用 {
public static void main(String[] args) {
//创建集合对象
TreeSet<day10Student> ts = new TreeSet<>(new Comparator<day10Student>() {
@Override
public int compare(day10Student s1, day10Student s2) {
//this.age - s.age
//s1,s2
int num = s1.getAge()-s2.getAge();
int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
//创建学生对象
day10Student s1 = new day10Student("xishi",29);
day10Student s2 = new day10Student("wangzhaojun",28);
day10Student s3 = new day10Student("diaochan",30);
day10Student s4 = new day10Student("yangyuhuan",33);
day10Student s5 = new day10Student("linqingxia",33);
day10Student s6 = new day10Student("linqingxia",33);
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//遍历集合
for (day10Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
}
}
package 集合框架.Set;
public class day10Student {
private String name;
private int age;
public day10Student(){
}
public day10Student(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
要求:按照总分从高到低出现
思路:
①定义学生类
②创建TreeSet集合对象,通过比较器排序进行排序
③创建学生对象
④把学生对象添加到集合
⑤遍历集合
import java.util.Comparator;
import java.util.TreeSet;
public class day11案例成绩排序 {
public static void main(String[] args) {
//创建TreeSet集合对象,通过比较器排序进行排序
TreeSet<day11Student> ts = new TreeSet<>(new Comparator<day11Student>() {
@Override
public int compare(day11Student s1, day11Student s2) {
//int num = (s2.getChinese() + s2.getMath())-(s1.getChinese()-s2.getMath());
int num = s2.getSum()-s1.getSum();
int num2 = num==0?s1.getChinese()-s2.getChinese():num;
int num3 = num2==0?s1.getName().compareTo(s2.getName()):num2;
return num3;
}
});
//创建学生对象
day11Student s1 = new day11Student("林青霞",98,100);
day11Student s2 = new day11Student("张曼玉",95,95);
day11Student s3 = new day11Student("王祖贤",100,93);
day11Student s4 = new day11Student("柳岩",100,97);
day11Student s5 = new day11Student("风清扬",98,98);
day11Student s6 = new day11Student("左冷禅",97,99);
//day11Student s7 = new day11Student("左冷禅",97,99);
day11Student s7 = new day11Student("赵云",97,99);
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
//遍历集合
for (day11Student s: ts){
System.out.println(s.getName()+","+s.getChinese()+","+s.getMath()+","+s.getSum());
}
}
}
package 集合框架.Set;
public class day11Student {
private String name;
private int chinese;
private int math;
public day11Student(){
}
public day11Student(String name,int chinese,int math){
this.name = name;
this.chinese = chinese;
this.math = math;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getSum(){
return this.chinese+this.getMath();
}
}
需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出
①创建set集合
②创建随机数对象
③判断集合的长度是不是小于10
是:产生一个随机数,添加到集合
回到3继续
④遍历集合
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
public class day12案例不重复的随机数 {
public static void main(String[] args) {
//创建set集合
//Set<Integer> set = new HashSet<>(); 不会排序
Set<Integer> set = new TreeSet<>(); //会排序
//创建随机数对象
Random r = new Random();
//判断集合的长度是不是小于10
while (set.size()<10){
//产生一个随机数,添加到集合
int number = r.nextInt(20)+1;
set.add(number);
}
//遍历集合
for (Integer i : set){
System.out.println(i);
}
}
}
Map
Map集合概述:
·Interface Map<K,V> K:键的类型;V:值的类型
·将键映射到值的对象;不能包含重复的键;每个键可以映射最多一个值
·举例:学生的姓名和学号
itheima001 林青霞
itheima002 张曼玉
itheima003 王祖贤创建Map集合的对象
·多态的方式
·具体的实现类HashMap
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class day1Map集合概述和使用 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<>();
//添加元素
//V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。
map.put("itheima001","林青霞");
map.put("itheima002","张曼玉");
map.put("itheima003","王祖贤");
map.put("itheima003","柳岩");
//输出集合对象
System.out.println(map);
}
}
V put(K key, V value) 添加元素
V remove(Object key) 根据键删除值对元素
void clear() 移除所有的键值对元素
boolean containsKey(Object key) 判断集合是否包含指定的键
boolean containsValue(Object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度也就是集合中键值对的个数
import java.util.HashMap;
import java.util.Map;
public class day2Map集合的基本功能 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<>();
//V put(K key, V value) 添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//V remove(Object key) 根据键删除值对元素
System.out.println(map.remove("郭靖"));
System.out.println(map.remove("郭想"));
//void clear() 移除所有的键值对元素
//map.clear();
//boolean containsKey(Object key) 判断集合是否包含指定的键
System.out.println(map.containsKey("郭靖"));
System.out.println(map.containsKey("张无忌"));
//boolean isEmpty() 判断集合是否为空
System.out.println(map.isEmpty());
//int size() 集合的长度也就是集合中键值对的个数
System.out.println(map.size());
//输出集合对象
System.out.println(map);
}
}
V get(Object key) 根据键获取值
Set<k>keySet() 获取所有键的集合
Collection<V>values() 获取所有值的集合
Set<Map.Entry<K,V>>entrySet() 获取所有键值对对象的集合
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class day3Map集合的获取功能 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<>();
//添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//V get(Object key) 根据键获取值s
System.out.println(map.get("张无忌"));
System.out.println(map.get("张三丰"));
//Set<k>keySet() 获取所有键的集合
Set<String> keySet = map.keySet();
for (String key: keySet){
System.out.println(key);
}
//Collection<V>values() 获取所有值的集合
Collection<String> values = map.values();
for (String value : values){
System.out.println(value);
}
}
}
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
遍历思路
1.把所有的丈夫集合起来
2.遍历丈夫的集合,获取每一个丈夫
3.根据丈夫去找对应的妻子**转换为Map集合中的操作
1.获取所有键的集合。用keySet()方法实现
2.遍历键的集合,获取每一个键。用增强for实现
3.根据键去找值。用get(Object key)方法实现**
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class day4Map集合的遍历1 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<>();
//添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//1.获取所有键的集合。用keySet()方法实现
Set<String> keySet = map.keySet();
//2.遍历键的集合,获取每一个键。用增强for实现
for (String key:keySet){
//3.根据键去找值。用get(Object key)方法实现
String value = map.get(key);
System.out.println(key+","+value);
}
}
}
//我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
//遍历思路
//1.获得所有结婚证的集合
//2.遍历结婚证的集合,得到每一个结婚证
//3.根据结婚证获取丈夫和妻子
//转换为Map集合中的操作:
//获取所有键值对对象的集合
//Set<Map.Entry<K,V>>entrySet():获取所有键值对对象的集合
//遍历键值对对象的集合,得到每一个键值对对象
//用增强for实现,得到每一个Map.Entry
//根据键值对对象获取每一个键值对对象
//用getKey()得到键
//用getValue()得到值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class day5Map集合的遍历2 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<>();
//添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//获取所有键值对对象的集合
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for(Map.Entry<String,String> me : entrySet){
//根据键值对对象获取每一个键值对对象
String key = me.getKey();
String value = me.getValue();
System.out.println(key+","+value);
}
}
}
需求:
键盘录入一个字符串,要求统计字符串中每个字符出现的次数。
举例:键盘录入 "aababcabcdabcde" 在控制台输出:"a(5)b(4)c(3)d(2)e(1)"
分析:
①我们可以把结果分成几个部分来看:a(5),b(4),c(3),d(2),e(1)
②每一个部分可以看成是:字符和字符对应的次数组成
③这样的数据,我们可以通过HashMap集合来存储,键是字符,值是字符出现的次数
注意:键是字符,类型应该是Character;值是字符出现的次数,类型应该是Integer
思路:
键盘录入一个字符串
创建HashMap集合,键是Character,值是Integer
遍历字符串,得到一个字符
拿得到的每一个字符作为键到HashMap集合中去找对应的值,看起返回值
如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
如果返回值不是null:说明该字符在集合中存在,把值加1,然后重新存储该字符和对应的值
遍历HashMap集合,得到键和值,按照要求进行拼接
输出结果
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
public class day10统计字符串中每个字符出现的次数 {
public static void main(String[] args) {
//键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
//创建HashMap集合,键是Character,值是Integer
//HashMap<Character,Integer> hm = new HashMap<Character,Integer>();
TreeMap<Character,Integer> hm = new TreeMap<Character,Integer>();
//遍历字符串,得到一个字符
for (int i = 0; i < line.length() ;i++) {
char key = line.charAt(i);
//拿得到的每一个字符作为键到HashMap集合中去找对应的值,看起返回值
Integer value = hm.get(key);
if (value == null){
// 如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
hm.put(key,1);
}else{
// 如果返回值不是null:说明该字符在集合中存在,把值加1,然后重新存储该字符和对应的值
value++;
hm.put(key,value);
}
}
//遍历HashMap集合,得到键和值,按照要求进行拼接
StringBuilder sb = new StringBuilder();
Set<Character> keySet = hm.keySet();
for (Character key : keySet){
Integer value = hm.get(key);
sb.append(key).append("(").append(value).append(")");
}
String result = sb.toString();
//输出结果
System.out.println(result);
}
}
Collections
Collections类的常用方法
·public static > void sort(List list):将指定的列表按升序排序
·public static void reverse(List <?>list):反转指定列表中元素的顺序
·public static void shuffle(List<?> list):使用默认的随机源随机排列指定的列表
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class day1Collections概述和使用 {
public static void main(String[] args) {
//创建集合对象
List<Integer> list = new ArrayList<>();
//添加元素
list.add(30);
list.add(20);
list.add(50);
list.add(10);
list.add(40);
//·public static <T extends Comparable <?super T>> void sort(List<T> list):将指定的列表按升序排序
Collections.sort(list);
//·public static void reverse(List <?>list):反转指定列表中元素的顺序
Collections.reverse(list);
//·public static void shuffle(List<?> list):使用默认的随机源随机排列指定的列表
Collections.shuffle(list);
System.out.println(list);
}
}
需求:ArrayList存储学生对象,使用Collections对ArrayList进行排序
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序进行排序
思路:
①定义学生类
②创建ArrayList集合对象
③创建学生对象
④把学生添加到集合
⑤使用Collections对ArrayList集合排序
⑥遍历集合
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class day2ArrayList集合存储学生并排序 {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<day2Student> array = new ArrayList<>();
//创建学生对象
day2Student s1 = new day2Student("linqingxia",30);
day2Student s2 = new day2Student("zhangmanyu",35);
day2Student s3 = new day2Student("wangzuxian",33);
day2Student s4 = new day2Student("liuyan",33);
//把学生添加到集合
array.add(s1);
array.add(s2);
array.add(s3);
array.add(s4);
//使用Collections对ArrayList集合排序
Collections.sort(array, new Comparator<day2Student>() {
@Override
public int compare(day2Student s1, day2Student s2) {
int num = s1.getAge() - s2.getAge();
int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
//遍历集合
for (day2Student s : array){
System.out.println(s.getName()+","+s.getAge());
}
}
}