ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 集合框架 [TOC] ## 什么是集合 Java中的集合是工具类,可以存储任意数量的具有共同属性的对象。 >[info] 集合类存放于java.util包中。 > 集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用 >[success] 在集合框架中,主要分为 Collection 和 Map 两大接口。 > 在 Collection 中又分为 List (有序集合) 和 Set (无序集合)。List 和 Set 都是接口。 > 其中Collection存储的是元素,Map存储的key-value键值对。 >[warning] 集合框架存储的元素可以是不定长的,即可以任意的添加,但是数组在定义的时候就确定了长度。实际开发中,对于同类型数据的结构,一般使用 Collection 结构会较多。 ## Collection ![](https://img.kancloud.cn/57/5a/575a8b4a5f479df91165f236ea99381b_1004x562.png) 在Collection中,根据不同的数据结构是使用方法,分为Set(无序的数据集合,元素不可重复)、Queue(队列)、List(有序的集合,元素可以重复)。 在Collection中的定义中Interface Collection,是一种泛型结构,意思是在使用Collection定义对象的时候,需要指定存储的元素数据类型(强调:**在集合中存储的数据元素必须都是引用数据类型**)。 ### List list中的内容是有序的并且可以重复的,我们也称之为序列; list可以精确的控制每个元素的插入位置,或者删除某个位置的元素; >[info] 是实际开发中用的最多的一种数据结构,存储的单个元素,使用**泛型**去强制约束 List 中存放的是一致的数据类型 > 在List接口中,最常用的实现类为ArrayList和LinkedList,其中ArrayList是运用最多的。 **语法** ~~~ List<E> list = new ArrayList<E>(); ~~~ **插入元素** add() **遍历元素** * 通过元素索引下标方式 for 循环 * 通过 foreach 循环 * 通过迭代器 Iterator **删除元素** 如果通过遍历去查找相关元素进行删除的时候,不要使用 list.remove(int index) 该方法,因为使用该方法,会动态的直接改变集合的元素结构,导致遍历的不完整或者有错误。要使用迭代器遍历集合,调用 Iterator.remove() 方法删除。 ### Set 不详细阐述,在遍历的时候不能使用索引方式,只能通过迭代器和 foreach。 ## Map ![](https://img.kancloud.cn/e1/bd/e1bd5e2144e1efcd3111df395aea5eb5_954x491.png) 类似的可以理解给集合元素中的值定义了一个 Key 键(遍历),之后可以通过相关的方法快速的定位到具体的 Value 中。 Map中存储是key-value键值对,在Map接口中,我们主要使用的实现类为HashMap。 在使用HashMap类的时候,插入的顺序和最后遍历出来的顺序可以是有差异的,因为本身HashMap结构它是无序的。 通过map.put(key, value)方法进去数据的写入,同样的要注意使用泛型。(强调:**Map中的key键和value值的数据元素必须都是引用数据类型**)。 * * * **语法** ~~~ Map<k,v> map= new HashMap<k,v>(); ~~~ Map集合中的一些注意点: * key必须是唯一的,不唯一,那么后面的value会把前面的value覆盖 * 对于HashMap,key可以为空,value可以为空,也可以不为空 * HashTable的key和value不能为空 * properties的key和value必须为String类型的 **获取某个 key 的 value** Value get(Key) **如何遍历 Map 结构** 获取 Map 的 Key 集合,通过遍历 Key 集合,获取 Value 值。 1. 获取 key 集合:map.keySet(); 2. 遍历 Key 集合:iterator; 3. 获取 Value 值:get(key); ## 开发注意事项 在实际开发中,List 一般使用 ArrayList 实现类去构建,Map 一般使用 HashMap 实现类去构建。 要掌握对于 List 和 Map 的添加元素、遍历元素。 要认识集合框架中关于对象在内存中的存储方法。 ## 本节课的代码片段 **代码运行内存图** ![](https://img.kancloud.cn/b1/45/b14565f9fea59d7132b628f762dcf8d1_1979x849.png) Clazz.java ~~~ package com.ntqingniao.j96.bean; import java.util.List; public class Clazz { private String name; private String code; private List<Student> students; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } } ~~~ Clazz2.java ~~~ package com.ntqingniao.j96.bean; import java.util.Map; public class Clazz2 { private String name; private String code; private Map<String, Student> stus; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public Map<String, Student> getStus() { return stus; } public void setStus(Map<String, Student> stus) { this.stus = stus; } } ~~~ Client.java ~~~ package com.ntqingniao.j96.bean; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Client { public static void main(String[] args) { Student pxj = new Student("彭贤君", "001"); Student hjn = new Student("黄佳男", "002"); Clazz j96 = new Clazz(); j96.setName("Java96班"); j96.setCode("java96"); // Step1:学生类型的集合定义完成了 List<Student> stus = new ArrayList<Student>(); // Step2: 添加数据 stus.add(pxj); stus.add(hjn); // Step3: 追加一个新的学生 Student ljn = new Student("陆佳楠", "003"); stus.add(ljn); // Step4: 设置班级学生属性 j96.setStudents(stus); // for (int i = 0; i < j96.getStudents().size(); i++) { // Student stu = j96.getStudents().get(i); // if (stu.getName().equals("黄佳男")) { // stu.setCode("004"); // } // } // for (int i = 0; i < j96.getStudents().size(); i++) { // // 打印对象,如果没有显式的调用toString()方法,编译器也会执行toString(); // System.out.println(j96.getStudents().get(i)); // } // // for (int i = 0; i < stus.size(); i++) { // System.out.println(stus.get(i)); // } // // for (Student stu : stus) { // System.out.println(stu); // } // // for (Student stu : stus) { // if (stu.getName().equals("黄佳男")) { // stu.setCode("005"); // } // } // for (int i = 0; i < j96.getStudents().size(); i++) { // Student stu = j96.getStudents().get(i); // System.out.println(stu.getName()); // if (stu.getName().equals("彭贤君")) { // j96.getStudents().remove(i); // 这样的实现是有问题的 // System.out.println(j96.getStudents().size()); // } // } // // for (Student stu : stus) { // System.out.println(stu); // } // 使用迭代器遍历 // Step1:创建迭代器 Iterator<Student> it = stus.iterator(); while (it.hasNext()) { Student stu = it.next(); System.out.println(stu); if (stu.getName().equals("黄佳男")) { it.remove(); } } System.out.println("处理完的结果======================"); it = stus.iterator(); while (it.hasNext()) { Student stu = it.next(); System.out.println(stu); } } } ~~~ Client2.java ~~~ package com.ntqingniao.j96.bean; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Client2 { public static void main(String[] args) { Student pxj = new Student("彭贤君", "001"); Student hjn = new Student("黄佳男", "002"); Clazz2 j96 = new Clazz2(); j96.setName("Java96班"); j96.setCode("java96"); Map<String, Student> stus = new HashMap<String, Student>(); stus.put("001", pxj); stus.put("002", hjn); j96.setStus(stus); Student stu = stus.get("001"); System.out.println(stu.getName()); System.out.println(stus.containsKey("003")); // 遍历Map // 第一步:获取Map中的Key集合 Set<String> keySet = stus.keySet(); // 第二步:迭代Key集合 Iterator<String> keyIt = keySet.iterator(); while (keyIt.hasNext()) { String key = keyIt.next(); // 根据Key获取Value Student value = stus.get(key); System.out.println(key + "=" + value); } } } ~~~ Client3.java ~~~ package com.ntqingniao.j96.bean; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Client3 { public static void main(String[] args) { Student pxj = new Student("彭贤君", "10", 20); Student hjn = new Student("黄佳男", "008",19); Student liuxiaowei = new Student("刘晓卫", "002",22); Student liuxiaowei2 = new Student("刘晓卫", "005",15); Student liuxiaowei3 = new Student("刘晓卫", "001",25); Student liuxiaowei4 = new Student("刘晓卫", "004",13); List<Student> stus = new ArrayList<Student>(); stus.add(pxj); stus.add(hjn); stus.add(liuxiaowei); stus.add(liuxiaowei2); stus.add(liuxiaowei3); stus.add(liuxiaowei4); Collections.sort(stus); for(Student stu : stus) { System.out.println(stu); } } } ~~~ Student.java ~~~ package com.ntqingniao.j96.bean; public class Student implements Comparable<Student>{ private String name; private String code; private int age; public Student(String name, String code) { super(); this.name = name; this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, String code, int age) { super(); this.name = name; this.code = code; this.age = age; } @Override public String toString() { return "Student [name=" + name + ", code=" + code + ", age=" + age + "]"; } @Override public int compareTo(Student o) { if (this.age > o.age) { return 1; } else if (this.age == o.age) { return 0; } else { return -1; } } } ~~~ **扑克牌实例程序** >[danger] 由于出现花色特殊的字符,需要把Java文件的字符编码定义为 UTF-8 Constants.java ~~~ package com.ntqingniao.j96.bean; public class Constants { public static String[] FOLLOWS = {"♠","♥","♣","♦"}; public static int[] NUMBERS = {2,3,4,5,6,7,8,9,10,11,12,13,14}; public static String[] NUMBERS_STR = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"}; } ~~~ Poker.java ~~~ package com.ntqingniao.j96.bean; public class Poker { private String follow; private int number; public int compare(Poker p1, Poker p2) { return 0; } public Poker(String follow, int number) { super(); this.follow = follow; this.number = number; } public String getFollow() { return follow; } public void setFollow(String follow) { this.follow = follow; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } @Override public String toString() { return this.getFollow() + Constants.NUMBERS_STR[this.getNumber()-2]; } } ~~~ Client4.java ~~~ package com.ntqingniao.j96.bean; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Client4 { public static void main(String[] args) { List<Poker> pokers = new ArrayList<Poker>(); for (String follow : Constants.FOLLOWS) { for (int number : Constants.NUMBERS) { Poker poker = new Poker(follow, number); pokers.add(poker); } } int i = 0; for (Poker poker : pokers) { System.out.print(poker + " "); i++; if (i % 13 == 0) { System.out.println(); } } System.out.println("==========洗牌=========="); for (int j = 0; j < 5; j++) { System.out.println("===========第" + (j + 1) + "副牌=========="); Collections.shuffle(pokers); i = 0; for (Poker poker : pokers) { System.out.print(poker + " "); i++; if (i % 13 == 0) { System.out.println(); } } } } } ~~~ ## 练习 1. **定义一个方法listTest(ArrayList al, Integer s),要求返回s在al里面第一次出现的索引,如果s没出现过返回-1。** ~~~java import java.util.ArrayList; import java.util.List; public class ListTestDemo { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(7); list.add(4); list.add(2); list.add(1); list.add(5); list.add(2); System.out.println(ListTest(list, 2)); System.out.println(list.indexOf(7)); } public static int ListTest(List<Integer> al, Integer s) { for(int i = 0; i < al.size(); i++) { if(al.get(i).equals(s)) {//此时集合中和s都是引用数据类型。判断是否相等采用的是equals方法 return i; } } return -1; } } ~~~ 2. **现在有一个map集合如下:** ~~~ Map map = new HashMap(); map.put(1, "张三丰"); map.put(2, "周芷若"); map.put(3, "汪峰"); map.put(4, "灭绝师太"); ~~~ **要求:** 1. **遍历集合,并将序号与对应人名打印。** 2. **向该map集合中插入一个编码为5姓名为李晓红的信息** 3. **移除该map中的编号为1的信息** 4. **将map集合中编号为2的姓名信息修改为"周林"** ~~~java import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class MapStudy { public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1,"张三丰"); map.put(2,"周芷若"); map.put(3,"汪峰"); map.put(4,"灭绝师太"); //新增 map.put(5, "李晓红"); //删除 map.remove(1); //修改(覆盖) map.put(2, "周林"); //遍历 Set<Integer> set = map.keySet(); Iterator<Integer> it = set.iterator(); while(it.hasNext()) { Integer key = it.next(); System.out.println("序号为:" + key + ",姓名为:" + map.get(key)); } } } ~~~ 3. **有2个数组,第一个数组内容为:\[黑龙江省,浙江省,江西省,广东省,福建省\],第二个数组为:\[哈尔滨,杭州,南昌,广州,福州\],将第一个数组元素作为key,第二个数组元素作为value存储到Map集合中。如{黑龙江省=哈尔滨, 浙江省=杭州, …}。** ~~~java import java.util.HashMap; import java.util.Map; public class MapStudy { public static void main(String[] args) { String[] province = {"黑龙江省","浙江省","江西省","广东省","福建省"}; String[] city = {"哈尔滨","杭州","南昌","广州","福州"}; Map<String,String> map = new HashMap<String,String>(); for(int i = 0; i < province.length; i++) { map.put(province[i], city[i]); } System.out.println(map); } } ~~~ 4. **双色球规则:双色球每注投注号码由6个红色球号码和1个蓝色球号码组成。红色球号码从1—33中选择;蓝色球号码从1—16中选择;请随机生成一注双色球号码。(要求同色号码不重复)**