一、LinkedHashSet
1、特点:
A、具有可预知迭代顺序 有序的
B、哈希表和链表实现
C、此实现不是同步的 在多线程是不安全的
2、案例
step01需求: 键盘录入一串字符abcabdc 按照顺序排列这一处啊字符(去除重复)==>abcd
step02分析
A、有序
B、唯一(去除重复)
C、使用LinkedHashSet
step03代码
package com.gkd.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 linked=new LinkedHashSet(); //遍历数组将数组中的字符存入集合 for (char c:array){ linked.add(c); } System.out.println(linked); } }
二、Map
2.1简介
1、Map 翻译:地图 点==>具体的位置 Map是双列集合的顶级接口
生活中对应关系:ip==>主机 丈夫==>妻子 人==>身份证
2、特点
将键映射到值的对象 key键 value值
B、一个映射不能包含重复的键;每个键最多只能映射到一个值 键值对 键是唯一的
3、实现类
HashMap TreeMap
4、总结
键值对映射的集合
2.2单列集合与双列集合的比较
2.3Map集合常用方法
方法的名称 | 方法的描述 |
void clear() | 清除所有的元素 |
boolean containsKey(Object key) | 判断键是否存在 |
boolean containsValue(Object value | 判断值是否存在 |
Set> entrySet() | 用于遍历Map集合 |
V get(Object key | 根据键获取值 |
boolean isEmpty() | 判断集合是否为空 |
Set keySet() | 获取所有的键(key) |
V put(K key, V value) | 增加(键不存在)/修改(键存在) |
V remove(Object key | 根据键删除集合中键值对 |
int size() | 获取集合的长度 |
Collection values() | 获取所有的值 |
代码:
package com.gkd.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("阿廖","干就是干"); System.out.println(m); //判断键是否存在 System.out.println(m.containsKey("凤舞")); System.out.println(m.containsKey("云曦")); //判断值是否存在 System.out.println(m.containsValue("科大第一米莱迪")); System.out.println(m.containsValue("gg")); //根据键来获取值 System.out.println(m.get("老王")); //删除键值对 m.remove("覃老六"); System.out.println(m); //获取所有的键 Set set = m.keySet(); System.out.println(set); //获取所有的值 Collection val = m.values(); System.out.println(val); //获取集合的长度 System.out.println(val.size()); //清空集合 m.clear(); //判断集合是否为空 System.out.println(m.isEmpty()); } }
2.4Map集合遍历
2.4.1第一种方式
代码:
package com.gkd.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)); } } }
2.4.2第二种方式
代码:
package com.gkd.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 en= (Map.Entry) obj; //调用对象的方法获取键值对 System.out.println(en.getKey()+"\t"+en.getValue()); } } }
2.5案例
step01需求:键盘录入一串字符串 统计每一个字符出现的字数 例如:abcabcc a==2 b==2 c==3
step02分析
A、使用Sanner
B、将字符串转换为字符数组 boolean containsKey(Object key)
C、使用键值对的集合 Map集合 键:字符 值:字数
boolean containsKey(Object key)
判断键是否在集合中存在
获取上一次的记录+1
如果键不存在
将值设置为1
package com.gkd.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 ch:array){ // //判断是否已经有了键 // if (m.containsKey(ch)){ // m.put(ch,(Integer)(m.get(ch))+1); // }else { // m.put(ch,1); // } //使用三元运算符 m.put(ch,m.containsKey(ch)?(Integer)(m.get(ch))+1:1); } System.out.println(m); } }
三、HashMap
3.1简介
1、Map接口的是实现类
2、基于哈希表结构存储
3、允许使用null值和null键
4、此实现不是同步的 在多线程中不安全的
5、构造一个具有默认初始容量 16
3.2HashMap与HashSet的比较
相同点:
A、都是使用hash结构来存储 HashSet集合的底层也是使用HashMap来进行存储
B、HashSet使用HashMap的键的结构 保证数据的唯一性
3.3LinkedHashMap
A、Map 接口的哈希表和链接列表实现
B、具有可预知的迭代顺序
C、此实现不是同步的 在多线程中不安全
四、泛型
4.1简介
1、使用场景:在定义集合的时候不确定其数据类型 但是在实例化集合的时候可以确定其数据类型 就可以使用泛型
泛型其实就是一个变量 这个变量用来接受其数据类型
2、泛型使用:
A、在实例化对象的时候必须确定其数据类型
B、例子:List 对象名=new ArrayList();
C、注意点:
a、前后的泛型都必须是一致的
b、在jdk1.7之后 出现了菱形的泛型 后面的泛型可以省略
c、泛型只能使用引用数据类型 不能使用基本数据类型可以使用包装类
3、泛型的好处
A、避免强制类型转换
B、将运行时的错误提前到编译时的错误
4、使用泛型的符号
泛型的符号一般是使用的都是一些大学的字母 任意的大写字母都是可以的
常用的大写字母:E K T W Z……
4.2定义泛型类
1、语法:
返回修饰符 class 类名{
类中的所有成员都可以使用类的泛型
}
2、例子:
public class PageInfo{
}
代码-泛型类
package com.gkd.test03; 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); } }
代码-泛型测试类
package com.gkd.test03; public class Test01 { public static void main(String[] args) { //实例化对象 MyArrayList<Integer> myl01=new MyArrayList<Integer>(); myl01.set(990); System.out.println(myl01.get(0)); //实例化对象 MyArrayList<String> myl02=new MyArrayList<>(); myl02.set("老王"); System.out.println(myl02.get(0)); } }
4.3定义泛型方法
1、语法:
访问修饰符 返回值类型 方法名称(参数列表){
方法体;
return 返回值;
}
2、例子:
public void shoeInfo(T t){
}
3、说明:
可以给普通方法加泛型 也可以给静态方法加泛型
4、注意点:
A、普通成员方法可以使用类的泛型
B、静态方法不能使用类的泛型 因为静态资源优先加载
代码-定义泛型方法
package com.gkd.test04; public class My <T>{ public void showInfo(T t){ System.out.println(t); } public static <T>void show(T t){ System.out.println(t); } }
代码-定义测试类
package com.gkd.test04; public class Test02 { public static void main(String[] args) { My m=new My(); m.showInfo("sss"); m.showInfo(1222); My.show("yyds"); } }
4.4案例
step01需求:
step02分析
A、数组的数据类型使用泛型
B、数组交换元素需要通过索引
C、定义成泛型方法
step03代码-泛型方法
package com.gkd.test04; public class MyArrays { //静态需要在方法声明那里添加泛型,因为不能接收到类的泛型 public static <T> T[] showInfo(T[] array,int index1,int index2){ T temp=array[index1]; array[index1]=array[index2]; array[index2]=temp; return array; } }
step04代码-测试类
package com.gkd.test04; import java.util.Arrays; public class Test01 { public static void main(String[] args) { Integer[] nums= MyArrays.showInfo(new Integer[]{1,2,22,3377},1,3); System.out.println(Arrays.toString(nums)); } }
4.5定义泛型接口
1、体现:A、实现类确定其泛型 B、实现类不确定其泛型
2、实现类确定其泛型
public interface Iterator{
E next()
}
public final class Scanner implements Iterator
{
public String next()
}
3、实现类不确定泛型
public interface List {
boolean add(E e)
}
public class ArrayList implements List
{
public boolean add(E e)
}
step01代码-定义泛型接口
package com.gkd.test05; public interface Inner <T>{ void showInfo(T t); }
step02代码-定义泛型实现类
package com.gkd.test05; public class Impl implements Inner<String>{ @Override public void showInfo(String s) { System.out.println(s); } }
step03代码-定义测试类
package com.gkd.test05; public class Test01 { public static void main(String[] args) { //实例化实现类 Impl im=new Impl(); im.showInfo("yyds"); // im.showInfo(12); } }
step01代码-定义泛型接口
package com.gkd.test06; public interface Inner <T>{ void showInfo(T t); }
step02代码-定义泛型实现类
package com.gkd.test06; public class Impl<T> implements Inner<T>{ @Override public void showInfo(T t) { System.out.println(t); } }
step03代码-定义测试类
package com.gkd.test06; public class Test01 { public static void main(String[] args) { Inner in=new Impl(); in.showInfo("yyds"); in.showInfo(123); } }
4.6泛型通配符
1、泛型通配符 可以表示任意的数据类型 泛型通配符使用?来进行表示
2、泛型通配符一般作为方法的参数来使用 不能用来实例化集合的时候使用泛型通配符
3、泛型没有继承的概念
4、泛型通配符特殊符号
?extend E E本身或者是其子类
?super T T本身或者是其父类
4.7案例
step01需求:有两种学科 Html5和java 使用Map集合来存储不同的学院 遍历获取学员的信息
step02代码-定义学生类
package com.gkd.test06; public class Students { private int sid; private String name; private String sex; private String hobby; public Students() { } public Students(int sid, String name, String sex, String hobby) { this.sid = sid; this.name = name; this.sex = sex; this.hobby = hobby; } 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 getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } @Override public String toString() { return "Students{" + "sid=" + sid + ", name='" + name + '\'' + ", sex='" + sex + '\'' + ", hobby='" + hobby + '\'' + '}'; } }
step02代码-定义测试类
package com.gkd.test06; 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对象 Students stu01=new Students(1001,"老王","女","看大白腿"); Students stu02=new Students(1002,"凤舞","女","看小电影"); Students stu03=new Students(1003,"海芸","女","易烊千玺"); Students stu04=new Students(1004,"阿廖","男","学习"); //实例化Map集合存储Java学生 Map<Integer,Students> m1=new HashMap<>(); m1.put(1001,stu01); m1.put(1002,stu02); m1.put(1003,stu03); m1.put(1004,stu04); //实例化Html5对象 Students stu05=new Students(1005,"威威","男","想看小长腿"); Students stu06=new Students(1006,"狗仁","女","奋斗,努力"); Students stu07=new Students(1007,"洵洵","男","想学妹"); Students stu08=new Students(1008,"晓洁","男","看帅哥"); //实例化集合存储Html5对象 Map <Integer,Students>m2=new HashMap<>(); m2.put(1005,stu05); m2.put(1006,stu06); m2.put(1007,stu07); m2.put(1008,stu08); //实例化大的Map存储这两个对象 Map <String,Map <Integer,Students>> bigM=new HashMap<>(); bigM.put("java",m1); bigM.put("Html5",m2); //使用第一种方法获取 Set<String> strings = bigM.keySet(); for (String s:strings){ System.out.println(s); //根据获得的键获取值 Map<Integer, Students> inter = bigM.get(s); //获取所有键 Set<Integer> integers = inter.keySet(); for (Integer in:integers){ //根据键获取值 System.out.println(in+"\t"+inter.get(in)); } } System.out.println("========================================================="); //使用第二种方式获取 Set<Map.Entry<String, Map<Integer, Students>>> entries = bigM.entrySet(); //使用迭代器遍历 Iterator<Map.Entry<String, Map<Integer, Students>>> iterator = entries.iterator(); while (iterator.hasNext()){ //获取值 Map.Entry<String, Map<Integer, Students>> next = iterator.next(); System.out.println(next.getKey()); Map<Integer, Students> value = next.getValue(); Set<Map.Entry<Integer, Students>> entries1 = value.entrySet(); //使用迭代器遍历 Iterator<Map.Entry<Integer, Students>> iterator1 = entries1.iterator(); while (iterator1.hasNext()){ //获取值 Map.Entry<Integer, Students> next1 = iterator1.next(); System.out.println(next1.getKey()+"\t"+next1.getValue()); } } } }
4.8斗地主案例
step01需求-分析
代码:
package com.gkd.test07; import java.util.*; public class Test01 { public static void main(String[] args) { //有牌-生成牌 //定义连个数组分别存花色和点数 String [] colors=new String[]{"♦","♣","♥","♠"}; String [] nums={"3","4","5","6","7","8","9","10","J","Q","K","A","2"}; //定义一个Map集合 Map<Integer,String> map=new HashMap<>(); //定义一个变量来记录索引 int index=0; //生成一个List集合 List<Integer> list=new ArrayList<>(); //使用循环生成52张牌 for(String n:nums){ for (String c:colors){ //把生成的牌存放入Map集合中 map.put(index,c+n); //把索引放入List集合中 list.add(index); 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来存储每一个牌客的派 TreeSet<Integer> dipai=new TreeSet<>(); TreeSet<Integer> laowang=new TreeSet<>(); TreeSet<Integer> fengwu=new TreeSet<>(); TreeSet<Integer> aliao=new TreeSet<>(); for(int i=0;i<list.size();i++){ //最后三张牌发给底牌 if (i>=list.size()-3){ //添加,list集合中根据索引得到的值(值是牌的索引) dipai.add(list.get(i)); }else if (i%3==0){ laowang.add(list.get(i)); }else if(i%3==1){ fengwu.add(list.get(i)); }else if (i%3==2){ aliao.add(list.get(i)); } } //看牌 looks("底牌:",dipai,map); looks("老王:",laowang,map); looks("凤舞:",fengwu,map); looks("阿廖:",aliao,map); } //定义一个看牌的方法 //参数:看谁的牌,牌的索引值,牌的值 public static void looks(String name,TreeSet<Integer> treeS,Map<Integer,String> map){ //定义一个变量拼接牌 String s=""; for (Integer in:treeS){ s+=map.get(in)+" "; } System.out.println(name+"\t"+s); } }