day17学习笔记
一 回顾
1.hashcode值 方法:public int hashCode() 返回该对象的哈希码值 2.不能根据hashcode值判断是否是同一对象 3.String 重写hashcode方法 字符串内容相同 hashcode值相同 4.注意点:字符串中存在hash冲突 字符串内容不相同 但是hashcode值相同 5.HasshSet A.此类实现 Set 接口 B.由哈希表 在jdk1.8 之前 数组+链表 在jdk1.8之后 数组+链表 或者红黑树 C.此实现不是同步的 在多线程中是不安全的 6.TreeSet 特点: A. 自然顺序对元素进行排序 B.此实现不是同步的 在多线程中不安全 排序规则: 数值类型 按照升序(从小到大)来进行排列 字符串类型 按照首字母的ascmall码表来进行排序 自定义引用数据类型: 必须指定其排序规则 否则报错 自定义引用数据类型排序 A.在定义类的中实现 Comparable this -object >0 升序 this -object =0 表示是相同的元素 不会插入元素 this -object < 0 降序 步骤: a.实现这个接口 Comparable b.int compareTo(T o) B.在实例化集合指定排序规则 public TreeSet(Comparator<? super E> comparator)
二 LinkedHashSet
1.特点: A.具有可预知迭代顺序 有序 B.哈希表和链接列表实现 C.此实现不是同步的 在多线程中是不安全
三 案例
step01 需求 键盘录入一串字符 abcabdc 按照顺序排列这一串字符(去除重复 ) ==> abcd
step02 分析
A.有序 B.唯一 去除重复 C.使用 LinkedHashSet
step03 代码
package com.qf.test01;
import java.util.LinkedHashSet;
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) {
//实例化Scanner
Scanner input = new Scanner(System.in);
System.out.println("请输入一串字符");
//接收一串字符
String line = input.nextLine();
//将字符串转换为字符数组
char[] array = line.toCharArray();
//实例化集合存储数据
LinkedHashSet linkedHash = new LinkedHashSet();
//使用循环遍历数组
for (char c : array) {
linkedHash.add(c);
}
System.out.println(linkedHash);
}
}
四 Map
4.1 简介
1.Map 翻译: 地图 点====>具体的位置 Map是双列集合的顶级接口 生活中对应关系: ip ==>主机 丈夫 ==>妻子 人 ==>身份证 2.特点: A.将键映射到值的对象 key 键 value 值 B.一个映射不能包含重复的键;每个键最多只能映射到一个值 键值对 键是唯一 3.实现类 HashMap TreeMap 4.总结: 键值对映射的集合
4.2 单列集合与双列集合的比较
4.3 Map集合常用的方法
| 方法名称 | 方法描述 |
|---|---|
| void clear() | 清除集合中所有元素 |
| boolean containsKey(Object key) | 判断键是否存在 |
| boolean containsValue(Object value) | 判断值是否存在 |
| Set<Map.Entry<K,V>> entrySet() | 用于遍历map集合 |
| V get(Object key) | 根据键来获取值 |
| boolean isEmpty() | 判断集合是否为空 |
| Set<K> keySet() | 获取所有的键(key) |
| V put(K key, V value) | 增加(键不存在)/修改(键存在) |
| V remove(Object key) | 根据键删除集合中键值对 |
| int size() | 获取集合长度 |
| Collection<V> values() | 获取所有的值 |
代码
package com.qf.test02;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test01 {
public static void main(String[] args) {
//实例化集合
Map m = new HashMap();
//存入数据
m.put("吴亦凡","都美竹");
m.put("王宝强","马蓉");
m.put("罗志祥","时间管理大师");
m.put("严进林","小泽老师");
System.out.println(m);
//修改数据
m.put("吴亦凡","18岁少女");
System.out.println(m);
//判断键是否存在
System.out.println(m.containsKey("吴亦凡"));
System.out.println(m.containsKey("阿飞"));
//判断值是否存在
System.out.println(m.containsValue("马蓉"));
System.out.println(m.containsValue("龙泽老师"));
//根据键来获取值
System.out.println(m.get("吴亦凡"));
//根据键删除键值对
m.remove("吴亦凡");
System.out.println(m);
//获取所有键
Set set = m.keySet();
System.out.println(set);
//获取所有值
Collection coll = m.values();
System.out.println(coll);
//获取集合长度
System.out.println(coll.size());
//清空集合
m.clear();
//判断集合是否为空
System.out.println(m.isEmpty());
}
}
4.4 map集合遍历
4.4.1 第一种方式
代码
package com.qf.test02;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test02 {
public static void main(String[] args) {
//实例化集合
Map m = new HashMap();
m.put("黄晓明","杨颖");
m.put("邓超","孙丽");
m.put("贾乃亮","李小璐");
m.put("王宝强","马蓉");
//获取所有键
Set set = m.keySet();
//使用循环遍历
for(Object obj :set) {
System.out.println(obj+"\t"+m.get(obj));
}
}
}
4.4.2 第二种遍历方式
代码
package com.qf.test02;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test03 {
public static void main(String[] args) {
Map m = new HashMap();
m.put("黄晓明","杨颖");
m.put("邓超","孙丽");
m.put("贾乃亮","李小璐");
m.put("王宝强","马蓉");
//获取集合(每一组键值对的对象)
Set set = m.entrySet();
//使用循环遍历
for (Object obj : set) {
Map.Entry entry = (Map.Entry) obj;
//调用对象的方法获取键值对
System.out.println(entry.getKey()+"\t"+entry.getValue());
}
}
}
4.5 案例
step01 需求:键盘录入一串字符 统计每一个字符出现的次数 例如 abcabcc ==> a ==2 b ==2 c==3
step02 分析
A.使用Scanner B.将字符串转换为字符数组 public char[] toCharArray() C.使用键值对的集合 Map集合 键: 字符 值 次数 boolean containsKey(Object key) 如果键在集合中存在 获取上一次的记录+1 如果键不存在 将值设置为1
step03 代码
package com.qf.test02;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Test04 {
public static void main(String[] args) {
//实例化Scanner
Scanner input = new Scanner(System.in);
System.out.println("请输入一串字符");
String line = input.nextLine();
//将字符串转换为字符数组
char[] array = line.toCharArray();
//实例化集合
Map m = new HashMap();
//使用循环遍历
for (char c: array) {
//判断键是否存在
// if (m.containsKey(c)) {
// m.put(c,(Integer)(m.get(c))+1);
// }else {
// m.put(c,1);
// }
//使用三元运算符
m.put(c,(m.containsKey(c) ? (Integer)(m.get(c))+1 :1));
}
System.out.println(m);
}
}
五 HashMap
5.1 简介
1.Map接口的实现类 2.基于基于哈希表结构存储 3.允许使用 null 值和 null 键 4.此实现不是同步的 在多线程中不安全的 5.构造一个具有默认初始容量 16
5.2 HashMap 与HashSet的比较
A.都是使用hash结构表来进行存储 HashSet集合的底层也是使用HashMap来进行存储 B.HashSet使用 HashMap的键的数据结构 保证数据的唯一性
六 LinkedHashMap
A.Map 接口的哈希表和链接列表实现 B.具有可预知的迭代顺序 C.此实现不是同步的 在多线程中是不安全的
代码
package com.qf.test02;
import java.util.LinkedHashMap;
public class Test05 {
public static void main(String[] args) {
//实例化集合
LinkedHashMap map = new LinkedHashMap();
map.put("a","薛之谦");
map.put("c","周杰伦");
map.put("b","林俊杰");
map.put("d","毛不易");
System.out.println(map);
}
}
七 泛型
7.1 简介
1.使用场景:在定义集合时候不确定其数据类型 但是在实例化集合的时候可以确定其数据类型 就可以使用泛型
泛型其实就是一个变量 这个变量用于来接收其数据类型
2.泛型使用:
A.在实例化对象的时候必须确定其数据类型
B.例子:List<泛型> 对象名 = new ArrayList<泛型>();
C.注意点:
a.前后的泛型都必须是一致
b.在jdk1.7 之后 出现了菱形的泛型 后面的泛型可以省略
c.泛型只能使用引用数据类型 不能使用基本数据类型
3.泛型的好处:
A.避免强制类型转换
B.将运行时错误提前到编译期间
4.使用泛型的符号
泛型的符号使用的都是一些大写的字母 任意的大写字母都是可以
常用的大写字母: E K V T W Z......
7.2 定义泛型类
1.语法:
访问修饰符 class 类名<泛型> {
类中的所有成员都可以使用类的泛型
}
2.例子:
public class PageInfo<T>{
}
step 01-代码-定义泛型类
package com.qf.test04;
import java.util.ArrayList;
import java.util.List;
/**
* 定义泛型类
* @param <T>
*/
public class MyArrayList<T>{
//实例化集合
List<T> list = new ArrayList<>();
//设置集合中元素
public void set(T t){
list.add(t);
}
//获取集合中元素
public T get(int index){
return list.get(index);
}
}
step02 -代码-测试类
package com.qf.test04;
public class Test01 {
public static void main(String[] args) {
//实例化对象
MyArrayList<Integer> list01 = new MyArrayList<>();
list01.set(11);
System.out.println(list01.get(0));
//实例化对象
MyArrayList<String> list02 = new MyArrayList<>();
list02.set("张三");
System.out.println(list02.get(0));
}
}
7.3 定义泛型方法
1.语法:
访问修饰符<泛型>返回值类型 方法名称(参数列表) {
方法体;
return 返回值;
}
2.例子:
public <T> void showInfo(T t){
}
3.说明:
可以给普通方法加泛型 也可以给静态方法加泛型
4.注意点:
A.普通成员方法可以使用类的泛型
B.静态方法不能使用类的泛型 因为静态资源优先加载
step01-代码-定义泛型方法
package com.qf.test05;
public class My <T>{
public void showInfo(T t){
System.out.println(t);
}
public static <T> void show(T t){
System.out.println(t);
}
}
step02-代码-定义测试类
package com.qf.test05;
public class Test01 {
public static void main(String[] args) {
My m = new My();
m.showInfo("sss");
m.showInfo(12);
My.show("kk");
}
}
7.4 案例
step01 需求
step02 分析
A.数组数据类型使用泛型 B.数组交换元素需要通过索引 C.定义成泛型方法
step03 代码-定义泛型方法
package com.qf.test06;
public class MyArrays {
public static <T>T[] showInfo(T[] arrays, int index1,int index2) {
//交互数组的元素
T temp = arrays[index1];
arrays[index1] =arrays[index2];
arrays[index2] = temp;
return arrays;
}
}
step04-代码-测试类
package com.qf.test06;
import java.util.Arrays;
public class Test01 {
public static void main(String[] args) {
Integer[] nums = MyArrays.showInfo(new Integer[]{2, 3, 4, 5}, 0, 1);
System.out.println(Arrays.toString(nums));
}
}
7.5 定义泛型接口
1.体现:A.实现类确定其泛型 B.实现类不确定其泛型
2.实现类确定其泛型
public interface Iterator<E>{
E next()
}
public final class Scanner implements Iterator<String>{
public String next()
}
3.实现类不确定其泛型
public interface List<E> {
boolean add(E e)
}
public class ArrayList<E> implements List<E>{
public boolean add(E e)
}
第一种体现
step01-定义接口
package com.qf.test07;
public interface Inner <T>{
void showInfo(T t);
}
step02-定义实现类
package com.qf.test07;
public class Impl implements Inner<String> {
@Override
public void showInfo(String s) {
System.out.println(s);
}
}
step03-测试类
package com.qf.test07;
public class Test01 {
public static void main(String[] args) {
//实例化实现类
Impl im = new Impl();
im.showInfo("sssss");
//im.showInfo(12);
}
}
第二种体现
step01-代码-定义接口
package com.qf.test08;
public interface Inner <T>{
void showInfo(T t);
}
step02-代码-实现类
package com.qf.test08;
public class Impl<T> implements Inner<T> {
@Override
public void showInfo(T t) {
System.out.println(t);
}
}
step03-代码-测试类
package com.qf.test08;
public class Test01 {
public static void main(String[] args) {
Inner in = new Impl();
in.showInfo("111");
in.showInfo(12);
}
}
7.6 泛型通配符
1.泛型通配符 可以表示任意的数据类型 泛型通配符使用?来进行表示
2.泛型通配符一般作为方法的参数使用 不能实例化集合的时候使用泛型通配符
3.泛型没有继承的概念
4.泛型通配符特殊符号
? extends E E本身或者是其子类
? super T T本身或者是其父类
代码
package com.qf.test09;
import javax.print.attribute.standard.NumberUp;
import java.util.ArrayList;
import java.util.List;
public class Test01 {
public static void main(String[] args) {
// List<String> li = new ArrayList<>();
// li.add("张三");
// li.add("李四");
// li.add("王五");
//showInfo(li);
//实例化集合
//List<?> list = new ArrayList<?>();
List<Number> list01 = new ArrayList<>();
showInfo(list01);
List<Integer> list02 = new ArrayList<>();
showInfo(list02);
List<Object> list03 = new ArrayList<>();
showInfo(list03);
}
//Integer Number Object
//Integer extends Number
//Number extends Object
public static void showInfo(List<? super Number> list){
/* for (Object obj : list) {
System.out.println(obj);
}*/
}
}
7.7 案例
step01 需求 千锋有两个学科 Html5 与java 使用map集合来存储不同的学员 遍历获取学员的信息
step02-代码-定义学生类
package com.qf.test09;
public class Student {
private int sid;
private String name;
private String sex;
private String hobbey;
public Student() {
}
public Student(int sid, String name, String sex, String hobbey) {
this.sid = sid;
this.name = name;
this.sex = sex;
this.hobbey = hobbey;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getHobbey() {
return hobbey;
}
public void setHobbey(String hobbey) {
this.hobbey = hobbey;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", hobbey='" + hobbey + '\'' +
'}';
}
}
step02-代码-定义测试类
package com.qf.test09;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Test02 {
public static void main(String[] args) {
//实例化java学生对象
Student stu01 = new Student(1001,"阿飞","男","各种会所");
Student stu02 = new Student(1002,"阿超","女","各种表妹");
Student stu03 = new Student(1003,"李焕荣","男","超级按摩师");
//实例化map集合存储java 学员
Map<Integer,Student> map = new HashMap<>();
map.put(1001,stu01);
map.put(1002,stu02);
map.put(1003,stu03);
//实例化Html5学生对象
Student stu04 = new Student(1004,"王统一","男","洗脚");
Student stu05 = new Student(1005,"李文强","男","撸代码");
Student stu06 = new Student(1006,"江伟","男","各种老师");
//实例化map集合存储Html学员
Map<Integer,Student> map1 = new HashMap<>();
map1.put(1004,stu04);
map1.put(1005,stu05);
map1.put(1006,stu06);
//实例化大的map来存储html与java的学员
Map<String,Map<Integer,Student>> bigMap = new HashMap<>();
bigMap.put("java",map);
bigMap.put("html5",map1);
//使用第一种遍历方式 获取键 通过键获取值
Set<String> set = bigMap.keySet();
for (String s :set){
System.out.println(s);
//根据键获取值
Map<Integer, Student> m = bigMap.get(s);
//获取所有键
Set<Integer> set01 = m.keySet();
//使用增强for循环遍历
for (Integer in :set01) {
System.out.println(in+"\t"+m.get(in));
}
}
System.out.println("==============================================");
//使用第二种遍历方式 将键值对封装对象 调用对象的方法获取
Set<Map.Entry<String, Map<Integer, Student>>> entries = bigMap.entrySet();
//使用迭代器遍历
Iterator<Map.Entry<String, Map<Integer, Student>>> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Map<Integer, Student>> next = iterator.next();
System.out.println(next.getKey());
Map<Integer, Student> map2 = next.getValue();
Set<Map.Entry<Integer, Student>> entries1 = map2.entrySet();
//转换迭代器
Iterator<Map.Entry<Integer, Student>> iterator1 = entries1.iterator();
while (iterator1.hasNext()) {
Map.Entry<Integer, Student> entry = iterator1.next();
System.out.println(entry.getKey() +"\t" + entry.getValue());
}
}
}
}
7.8 斗地主案例
step01 需求-分析
step02 代码
package com.qf.test10;
import java.util.*;
public class Test01 {
public static void main(String[] args) {
//生成扑克牌
//定义一个数组表示花色
String [] colors ={"♦","♣","♥","♠"};
//定义一个数组表示点数
String [] nums ={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
//实例化Map集合 存储扑克牌
Map<Integer,String> map = new HashMap<>();
//定义一个集合来存储其索引值
List<Integer> list = new ArrayList<>();
//定义一个变量来记录其索引
int index=0;
//使用循环生成52张牌
for (String n :nums) {
for (String w: colors) {
String num =w+n;
map.put(index,num);
list.add(index);
//索引需要递增
index++;
}
}
//System.out.println(index);
//生成小王
map.put(index,"小王");
list.add(index);
//索引递增
index++;
map.put(index,"大王");
list.add(index);
// System.out.println(map);
// System.out.println(list);
//洗牌 洗索引
Collections.shuffle(list);
//发牌 发索引
TreeSet dipai = new TreeSet();
TreeSet gaojin = new TreeSet();
TreeSet huazai = new TreeSet();
TreeSet feige = new TreeSet();
//使用循环遍历索引的集合
for (int i=0;i<list.size();i++) {
//发底牌
if (i >= list.size() -3) {
dipai.add(list.get(i));
}else if (i % 3 ==0) {
gaojin.add(list.get(i));
}else if (i % 3 ==1) {
huazai.add(list.get(i));
}else if (i % 3 ==2) {
feige.add(list.get(i));
}
}
//看牌
look("底牌",dipai,map);
look("高进",gaojin,map);
look("华仔",huazai,map);
look("飞哥",feige,map);
}
public static void look(String name,TreeSet<Integer> treeSet,Map<Integer,String> map){
String world="";
//遍历索引
for(Integer in : treeSet) {
String s = map.get(in);
world+=s+" ";
}
System.out.println(name+"\t"+world);
}
}








浙公网安备 33010602011771号