Java中的集合
集合就像是一个购物车,可以将购买的所有商品的存放在一个统一的购物车中
集合的概念
现实生活: 很多的事物凑在一起
数学中的集合: 具有共同属性的事物的总体
Java中的集合类: 是一种工具类,是一种容器,里面可以存储任意数量的相同属性的类。
集合的作用
在类的内部对数据进行组织
简单快速的搜索大数量的条目
有的集合借口,提供了一系列排列有序的元素,并且可以在序列中快速地插入或者删除元素
有的集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这 个关键字可以是任意类型
两个集合框架
Collection
- List
- Queue
- Set
List、Queue、Set的区别:
List和Queue中的元素是有序排列的
Set中的元素是无序排列的
graph TD Collection(Collection) --> List(List) List(List) -.-> ArrayList[ArrayList] List(List) -.-> LinkedList[LinkedList] Collection(Collection) --> Queue(Queue) Queue(Queue)-.-> LinkedList[LinkedList] Collection(Collection) --> Set(Set) Set(Set) -.-> HashSet[HashSet] style ArrayList fill:#F4493F,color:#fff style HashSet fill:#F4493F,color:#fff style List fill:#00A9D4,color:#fff style Set fill:#00A9D4,color:#fff在Collection中存储的是一个一个独立的对象
Map
在Map中会以<Key,Value>,也就是两个对象形成一个映射的关系的方式去存储数据,这有点像C#中的Diectory类型。
Collection 接口、子接口及其实现类
List接口及其实现类 --- ArrayList
- List中的元素可以是重复的并且是有序排列的,被称为序列
- List可以精确的控制每个元素的插入位置,或删除某个位置元素
- ArrayList --- 数组序列,是List的一个重要实现类
- ArrayList的底层是由数组实现的
实现功能 --- 模拟学生选课功能
- 选择课程(往集合中添加课程)
- 删除所选的某门课程(删除集合中的元素)
- 查看所选课程
- 修改所选课程
//: Course.java package com.faraj.collection; public class Course { public String name; public String id; public Course(String id, String name) { this.id = id; this.name = name; } }
创建课程类Course.java 由于是学习,类中的属性就用了public实际应用应该使用private修饰,然后添加getName; setName; getId; SetId方法;
//: Student.java package com.faraj.collection; import java.util.HashSet; import java.util.Set; public class Student { public String id; public String name; public Set<Course> courses; public Student(String id, String name){ this.id = id; this.name = name; this.courses = new HashSet<Course>(); } }
创建学生类Student.java
//: ListTest.java package com.faraj.collection; import java.util.*; public class ListTest { public List<Course> coursesToSelect; public ListTest() { this.coursesToSelect = new ArrayList<Course>(); } /** * 给courseToSelect添加元素 */ public void addTest() { Course cr1 = new Course("1", "数据库系统概论"); coursesToSelect.add(cr1); Course temp = coursesToSelect.get(0); System.out.println("已添加课程: " + temp.id + "-" + temp.name); coursesToSelect.add(0, new Course("2", "数据结构")); Course temp2 = coursesToSelect.get(0); System.out.println("已添加课程: " + temp2.id + "-" + temp2.name); coursesToSelect.add(0, new Course("2", "数据结构")); Course[] courses = new Course[]{ new Course("3", "线性代数"), new Course("4", "ASP网页设计") }; coursesToSelect.addAll(Arrays.asList(courses)); System.out.println("已添加课程: " + coursesToSelect.get(2).id + "-" + coursesToSelect.get(2).name); System.out.println("已添加课程: " + coursesToSelect.get(3).id + "-" + coursesToSelect.get(3).name); coursesToSelect.addAll(2, Arrays.asList( new Course("5", "面向对象编程"), new Course("6", "汇编语言"))); System.out.println("已添加课程: " + coursesToSelect.get(2).id + "-" + coursesToSelect.get(2).name); System.out.println("已添加课程: " + coursesToSelect.get(3).id + "-" + coursesToSelect.get(3).name); } /** * 获取集合中的所有元素 */ public void getTest() { for (int i = 0; i < coursesToSelect.size(); i++) { System.out.println("课程:" + coursesToSelect.get(i).id + " - " + coursesToSelect.get(i).name); } } /** * 通过迭代器遍历List */ public void iteratorTest() { Iterator<Course> it = coursesToSelect.iterator(); int i = 1; while (it.hasNext()) { Course cr = it.next(); System.out.println("课程" + i++ + ":" + cr.id + "-" + cr.name); } } /** * 使用foreach方式循环获得list中的所有元素 */ public void foreachTest() { int i = 1; for (Course cr : coursesToSelect) { System.out.println("课程" + i++ + ":" + cr.id + "-" + cr.name); } } /** * 修改List中的元素 */ public void modifyTest() { coursesToSelect.set(1, new Course("7", "Java语言设计")); } /** * 删除List中的元素 */ public void removeTest(){ coursesToSelect.remove(0); } public static void main(String[] args) { ListTest lt = new ListTest(); lt.addTest(); // lt.getTest(); // lt.iteratorTest(); lt.modifyTest(); lt.removeTest(); lt.foreachTest(); } }
创建备选课程类ListTest.java
package com.faraj.collection; import java.util.*; public class SetTest { public List<Course> coursesToSelect; public SetTest() { coursesToSelect = new ArrayList<Course>(); } public void add() { coursesToSelect.addAll( Arrays.asList( new Course("1", "数据库系统概论"), new Course("2", "C语言基础"), new Course("3", "Python语言实践"), new Course("4", "基础算法实现"), new Course("5", "汇编语言"), new Course("6", "Linux基础"), new Course("7", "面向对象编程")) ); } public void getAll() { for (Course c : coursesToSelect) { System.out.println(c.id + "--" + c.name); } } public static void main(String[] args) { SetTest st = new SetTest(); st.add(); st.getAll(); Student stu = new Student("1", "Faraj"); Scanner sca = new Scanner(System.in); System.out.println("Welcome Stu. " + stu.name + "to select courses. You should and only can select 3 course."); int num = 1; for (int i = 0; i < 3; i++) { System.out.println("Please choose NO. " + num + " course's ID"); num ++; String input = sca.next(); for (Course cor : st.coursesToSelect) { if (cor.id.equals(input)) { stu.courses.add(cor); } } } System.out.println("你选择了:"); for (Course stuC : stu.courses) { System.out.println(stuC.id + " - " + stuC.name); } } }
Map和HashMap
Map接口
- Map提供了一种映射关系,其中的元素是以键值()对的形式存储的,能够实现根据key查找value
- Map中的键值对是以Entry类型的对象实例形式存在
- key不可重复,但是value值可以重复
- 每个key只能映射一个值
- Map 支持范性,Map<K,V>
HashMap类
- HashMap是Map的一个重要实现类,也是最常用的,基于哈希表实现
- HashMap中的Entry对象是无序排列的
- Key和Value的值都可以为null, 但是一个HashMap中只能有一个Key值为null的映射(Key值不可重复)
案例:
功能说明: 通过Map<String,Student>进行学生信息管理
其中key为学生的ID,value为学生对象
通过键盘输入学生信息
对集合中的学生信息进行增删改查
创建MapTest.java
//: MapTest.java package com.faraj.collection; import java.util.*; public class MapTest { public Map<String, Student> students; public MapTest() { students = new HashMap<>(); } /** * 通过put方法在Map中添加entry(键值对) */ public void putTest() { Scanner scan = new Scanner(System.in); while (true) { System.out.println("请输入学生ID"); String id = scan.next(); int nextInput; if (students.get(id) == null) { System.out.println("请输入学生的姓名"); students.put(id, new Student(id, scan.next())); System.out.println("是否继续添加? 1继续 2退出"); nextInput = scan.nextInt(); if (nextInput != 1) { if (nextInput == 2) break; } } else { System.out.println("该ID已存在"); System.out.println("是否重新添加 1是 2退出"); while (true) { try { nextInput = scan.nextInt(); break; } catch (InputMismatchException e) { System.out.println("你输入的内容不合法,请重新输入"); } } if (nextInput != 1) { if (nextInput == 2) break; } } } } /** * 通过keySet取得遍历students */ public void keySetTest() { Set<String> keys = students.keySet(); System.out.println("现已添加学生人数:" + keys.size()); for (String stuId : keys) { System.out.println("学生(" + stuId + ")" + students.get(stuId).name); } } /** * 使用entrySet遍历students */ public void entrySetTest() { Set<Map.Entry<String, Student>> entries = students.entrySet(); System.out.println("学生总数:" + entries.size()); for (Map.Entry<String, Student> entry : entries) { System.out.println(entry.getKey() + " - " + entry.getValue().name); } } /** * 从Map中删除学生 */ public void removeTest() { Scanner scan = new Scanner(System.in); while (true) { System.out.println("请输入要删除的学生ID"); String id = scan.next(); if (students.get(id) == null) { System.out.println("找不到该学生ID"); System.out.println("重新输入请输入1,退出应输入2"); int next = scan.nextInt(); if (next != 1) { if (next == 2) { break; } } } else { System.out.println("学生(" + id + ")" + students.get(id).name + " 已被删除"); students.remove(id); System.out.println("重新输入请输入1,退出应输入2"); int next = scan.nextInt(); if (next != 1) { if (next == 2) { break; } } } } } /** * 通过Put方法更改学生姓名 */ public void modifyTest() { Scanner scan = new Scanner(System.in); while (true) { System.out.println("请输入要修改的学生的ID"); String stuId = scan.next(); Student stu = students.get(stuId); if (stu == null) { System.out.println("该ID的学生不存在,请重新输入"); continue; } System.out.println("当前学生(" + stuId + ")" + " - " + stu.name + ", 请输入修改后的名字"); String newName = scan.next(); Student newStu = new Student(stuId,newName); students.put(stuId,newStu); break; } } public static void main(String[] args) { MapTest mt = new MapTest(); mt.putTest(); mt.keySetTest(); mt.modifyTest(); mt.entrySetTest(); } }
判断coursesToSelect(List)中是否存在课程
在Course.java中重写equals方法
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Course)){ return false; } Course cour = (Course)obj; if (cour.name == null){ return this.name == null; }else{ return this.name.equals(cour.name); } }
在SetTest.java类中添加以下方法
public void containsTest() { System.out.println("请输入你要查找的名称"); Course inputCourse = new Course(); inputCourse.name = scan.next(); if (coursesToSelect.contains(inputCourse)) System.out.println("包含《" + inputCourse.name + "》"); else System.out.println("不包含《" + inputCourse.name + "》"); }
在SetTest.java的main方法中测试该方法
st.containsTest();
另外在List中还有一个containsAll()方法,其用法与contains差不多,就是传入的是一个比较的对象集合
判断Set中是否存在课程
将之前SetTest.java中的部分代码提取成一个单独的方法
public void createStuAndSelectCourse(){ Student stu = new Student("1", "Faraj"); System.out.println("Welcome Stu. " + stu.name + "to select courses. You should and only can select 3 course."); int num = 1; for (int i = 0; i < 3; i++) { System.out.println("Please choose NO. " + num + " course's ID"); num++; String input = scan.next(); for (Course cor : coursesToSelect) { if (cor.id.equals(input)) { stu.courses.add(cor); } } } System.out.println("你选择了:"); for (Course stuC : stu.courses) { System.out.println(stuC.id + " - " + stuC.name); } }
在该文件中创建一下方法
public void setContainsTest() { System.out.println("请输入学生选则的课程名称"); String name = scan.next(); Course inputCourse = new Course(); inputCourse.name = name; if (student.courses.contains(inputCourse)) { System.out.println("该学生选择了《" + inputCourse.name + "》"); } else { System.out.println("该学生并没有选择《" + inputCourse.name + "》"); } }
在main方法中调用新创建的两个方法
st.createStuAndSelectCourse(); st.setContainsTest();
运行程序发现HashSet中的contains方法告诉我们并没有包含课程
不用担心,这不是因为我们的代码写错了,而是……
HashSet的contains方法的实现机制
在Object这个根类中除了定义了上面通过Course类重写的equals()方法,还定义了一个**hashCode()**方法,这个方法返回的是对象的哈希码的值,当我们在调用HashSet的contains()方法的时候,其实先调用每个元素的hashCode获取它们的哈希码,如果哈希码相等的情况下,才会调用equals方法来判断是否相等,这有当这两个方法返回的值都是true的时候,contains()方法才会认定这个HashSet包含某个元素。
在Course类中添加hashCode方法的重写
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; }
然后重新启动程序,就能看到程序正常运行了
来源:https://www.cnblogs.com/mujey/p/12239434.html