1.泛型:
1.泛型概述:
泛型允许程序员在编写代码时使用一些以后才能确定的数据类型。
定义泛型:<字母> 如:<E>,<T>,<V>...
泛型的好处:
- 在编译时期起到限定数据类型的作用。
- 避免后期进行强制类型转换。
2.自定义泛型类:
泛型类格式:class 类名<泛型变量>{}
创建对象时确定泛型。
ArrayList<Integer> list=new ArrayList<>();
MyArrayList<String> list=new MyArrayList<>();
3.自定义泛型方法:
泛型方法格式:public <T> 返回值类型 方法名(T t){}
调用方法时传递什么类型,方法上的泛型就是什么类型。
ArrayList<String> list1=new ArrayList<>(); addElement(list1,"aa","bb","123"); public static <T> void addElement(Collection<T> coll,T t1, T t2,T t3){ ... }
4.自定义泛型接口:
泛型接口格式:修饰符 interface 接口名称<泛型变量>{}
可以让实现类选择当前功能需要操作的数据类型。
public interface DataOp<T> { void add(T t); T remove(int id); void set(int id,T t); T get(int id); } public class DataImpl implements DataOp<Student>{ ... }
5.泛型通配符:
泛型通配符作用:
- 泛型通配符一般用在方法的参数位置,限定参数的数据类型
- <?>: 表示任意类型。
- <? extends 指定类型>:指定类型或者指定类型的子类。
- <? super 指定类型>: 指定类型或者指定类型的父类。
public static void test1(ArrayList<?> list){ } public static void test2(ArrayList<? extends Number> list){ } public static void test3(ArrayList<? super Number> list){ }
2.可变参数:
可变参数指的是,可以让方法调用时,接收多个同类的参数。
可变参数的本质是一个数组,只是定义格式比较特殊。
/** * 可变参数的使用注意事项:如果有多个参数,可变参数必须写在最后一个 */ public class Demo1 { public static void main(String[] args) { int[] list=new int[]{12,15,63,48,78,45}; sout("aa",list); } public static void sout(String str, int... arr){ System.out.println(str); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
3.Collections工具类:
Collection:单列集合的根接口,是所有单列集合的统称。(Collection集合)
Collections:对集合进行操作的工具类。
public class Demo1 { public static void main(String[] args) { ArrayList<String> list=new ArrayList<>(); //1.addAll(Collection<? super T> c,T... elements):给集合对象批量添加元素。 Collections.addAll(list,"a","b","c","d","e","f","g"); System.out.println(list); //2.shuffle(List<?> list):打乱list集合元素的顺序。 Collections.shuffle(list); System.out.println(list); //3.sort(List<?> list):给集合中元素按照默认规则排序。 Collections.sort(list); System.out.println(list); //4.sort(List<?> list,Comparator<? super T> c):给集合中元素按照指定规则排序。 Collections.sort(list, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); System.out.println(list); } }
4.综合案例:
斗地主游戏:
在斗地主游戏中有一副扑克牌,一副扑克牌有54张,每张牌有花色和点数组成;
有3个玩家轮流分发54张牌,最后留3张底牌。编写程序模拟准备牌、洗牌、发牌、捋牌、看牌的逻辑。
1.准备牌,洗牌
2.发牌,看牌
3.排序
/** * 封装扑克信息 */ public class Poker { private String number; private String color; private int order; public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public Poker(String number, String color,int order) { this.number = number; this.color = color; this.order=order; } public Poker() { } @Override public String toString() { if (number.equals("大王")||number.equals("小王")){ return number; } return color+number; } }
public class Pokers { public static void main(String[] args) { ArrayList<Poker> list=new ArrayList<>(); String[] color={"♥","♠","♣","♦"}; String[] number={"3","4","5","6","7","8","9","10","J","Q","K","A","2"}; int order=0; for (String s1 : number) { for (String s : color) { Poker poker=new Poker(s1,s,order); list.add(poker); order++; } } Poker p1=new Poker(); p1.setNumber("小王"); p1.setOrder(order++); Poker p2=new Poker(); p2.setNumber("大王"); p2.setOrder(order); Collections.addAll(list,p1,p2); System.out.println("已准备好的未洗好牌:"+list); Collections.shuffle(list); System.out.println("该扑克牌已准备有:"+list.size()+"张"); System.out.println(); System.out.println("---------------------------------"); System.out.println("该扑克牌已经洗好牌:"+list); System.out.println(); System.out.println("---------------------------------"); System.out.println(); ArrayList<Poker> player1=new ArrayList<>(); ArrayList<Poker> player2=new ArrayList<>(); ArrayList<Poker> player3=new ArrayList<>(); ArrayList<Poker> dipai=new ArrayList<>(); for (int i = 0; i < list.size(); i++) { Poker p=list.get(i); if (i<list.size()-3){ if (i%3==0){ player1.add(p); }else if (i%3==1){ player2.add(p); }else { player3.add(p); } }else { dipai.add(p); } } System.out.println("第一个玩家的牌为:"+player1); System.out.println("第二个玩家的牌为:"+player2); System.out.println("第三个玩家的牌为:"+player3); System.out.println("剩下的底牌为:"+dipai); System.out.println(); System.out.println("--------------------------------------------------------------------------------------------------------------------------------------------------"); System.out.println(); Collections.sort(player1, ( o1, o2)-> o1.getOrder()-o2.getOrder()); Collections.sort(player2, ( o1, o2)-> o1.getOrder()-o2.getOrder()); Collections.sort(player3, ( o1, o2)-> o1.getOrder()-o2.getOrder()); System.out.println("第一个玩家洗好的牌为:"+player1); System.out.println("第二个玩家洗好的牌为:"+player2); System.out.println("第三个玩家洗好的牌为:"+player3); } }
5.Map集合:
1.Map集合概述,体系结构:
双列集合的元素是成对出现的,每一个元素称之为一个键值对。
2.Map集合常用API:
/**
* 使用Map集合的常用方法
*/
public class Demo1 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
//1.put添加键值对
map.put("张三","武汉");
map.put("李四","浙江");
map.put("王五","南京");
String value=map.put("王五","苏州");
System.out.println("被覆盖的值:"+value);
//2.remove删除键值对: 根据键删除键值对,然后把值返回
String value1=map.remove("王五");
System.out.println("被删除的值是:"+value1);
//3.get获取键对应的值
String value2=map.get("张三");
System.out.println("被获取的值是:"+value2);
//4.containsKey判断是否包含键
boolean value3=map.containsKey("李四");
System.out.println("是否包含李四:"+value3);
//5.size获取键值对的个数
int value4=map.size();
System.out.println("键值对有:"+value4+"个");
//6.isEmpty():判断集合是否为空
boolean isEmpty=map.isEmpty();
System.out.println("集合是否为空:"+isEmpty);
}
}
3.Map集合的遍历方式一:键找值
/**
* 遍历map集合:
* 1.键找值:
* 先找键,再找值
*/
public class Demo2 {
public static void main(String[] args) {
HashMap<String,Integer> map = new HashMap<>();
map.put("张三", 18);
map.put("李四", 20);
map.put("王五", 22);
//Set<K> keySet():获取集合中所有的键。
Set<String> keys=map.keySet();
for (String key : keys) {
Integer value=map.get(key);
System.out.println(key+"..."+value);
}
}
}
4.Map集合的遍历方式二:键值对
/**
* 遍历map集合:
* 2.键值对:
* 直接获取集合中的【键值对对象】
*/
public class Demo3 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("乌克兰", "泽连斯基");
map.put("俄罗斯", "普京");
map.put("美国", "拜登");
//Set<Map.Entry<K,V>> entrySet():取集合中所有的【键值对】
//Map.Entry:指的是Map集合中的内部类,每一个Entry对象,就表示一个键值对对象。
Set<Map.Entry<String,String>> entries =map.entrySet();
System.out.println(entries);
System.out.println();
for (Map.Entry<String, String> entry : entries) {
//K getKey():获取键值对的键。
String key=entry.getKey();
//V getValue():获取键值对的值。
String value=entry.getValue();
System.out.println(key+"..."+value);
}
}
}
5.Map集合的遍历方式三:lambda表达式
/**
* 遍历map集合:
* 3.lambda表达式:
* forEach方法遍历map集合(forEach(lambda表达式))
*/
public class Demo4 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("乌克兰", "泽连斯基");
map.put("俄罗斯", "普京");
map.put("美国", "拜登");
// map.forEach(new BiConsumer<String, String>() {
// @Override
// public void accept(String s, String s2) {
// System.out.println(s+"..."+s2);
// }
// });
/**
* default void forEach(BiConsumer<? super K,? super V> action):结合lambda遍历Map集合。
*/
map.forEach((key, value) -> System.out.println(key+"..."+value));
}
}
6.Map集合的实现类HashMap:
/**
* HashSet底层原理和HashMap是一模一样的。
* 特点:无序,无重复,无索引
* 数据结构:HashMap底层是哈希表结构的。
*
*
*/
public class Demo5 {
public static void main(String[] args) {
//HashSet存储元素:可以保证元素的唯一性,复写hashCode和equals
HashSet<String> set = new HashSet<>();
//往HashSet集合中添加元素,实际上底层是往Map的键位置添加
HashMap<Student,String> map=new HashMap<>();
map.put(new Student("张三",22),"湖北");
map.put(new Student("李四",56),"浙江");
map.put(new Student("王五",62),"杭州");
map.put(new Student("张三",22),"缙云");
System.out.println(map);
}
}
7.Map集合的实现类LinkedHashMap:
LinkedHashSet和LinkedHashMap一样底层数据结构依然是哈希表,只是额外地多了一个双链表的机制记录存储的顺序。
8.Map集合的实现类TreeMap:
TreeMap和TreeSet也是一样的,底层都是红黑树结构,可以对键进行排序。
键排序的方式:
默认排序:使用Comparable接口实现。(源码)
比较器排序:使用Comparator接口实现。(推荐)
public class test1 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入一个要统计的字符串。");
String str=sc.next();
HashMap<Character,Integer> map=new HashMap<>();
for (int i = 0; i < str.length(); i++) {
char cha=str.charAt(i);
if (map.containsKey(cha)){
int count=map.get(cha);
map.put(cha,++count);
}else {
map.put(cha,1);
}
}
map.forEach((character, integer) -> System.out.println(character+"字符的数量:"+integer));
}
}