Java 之集合框架 上(9)

时间:2021-01-08 19:25:00

Java 中的集合框架

如果一个类中存在很多相同类型的属性。

例如:学生类

学生可以选课,因此存在很多课程类型的属性。但是每个学生选择的课程的种类和数量是不一样的。

如果将每一个课程类型的属性都列到课程类中,这样就很难定义学生类了。

这时我们可以利用容器,把所有的课程类型的属性都加入到容器中,再将这个容器整体作为学生类的一个属性

上面所说的容器就是Java中的集合。

 

集合的概念:

现实生活中:很多的事物凑在一起。例如 超市中的购物车是商品的集合、军队是军人的集合

数学中的集合:具有共同属性的事物的总体。例如:有理数 和 整数

Java中的集合类:是一种工具类,就像是一个容器,储存任意数量的有共同属性的对象。

 

集合的作用:

1 在集合的内部,对数据进行组织

2 简单而快速的搜索大量的条目

3 有的集合接口,提供一系列排列有序的元素,并且可以在序列中间快速的插入或者删除有关的元素。

4 有的集合接口,提供映射关系,可以通过关键字(key)去快速查找到对应关系的唯一对象,可这个关键字可以使任意类型。

 

集合与数组的对比:

数组的长度或者说是容量是固定的,如果数组的长度不够用了,我们需要新建一个然后将原数组的元素复制进去,这样会很麻烦

集合的长度(容量)可以在使用过程中动态扩展

数组之能通过下标访问元素,类型固定,而有的集合可以通过任意类型查找所映射的具体对象

 

Java中的集合体系分为(两类):

Collection:

下面有三个接口 List、 Queue、 Set

List和Queue中存的元素是有序的,可以重复

Set中存的元素无序且不可重复

List下有一个常用的类ArraysList(数组序列)

Queue下有一个常用的类LinkedList(链表)List接口同样可以使用

Set下也有一个常用的类HashSet类

Map:

常用的有一个常用的实现类HashMap

 PS~:

Collection类中存储的为一个一个独立的对象(一个一个的单身汉)

Map类中会将<Key,Value>(Entry键值对)作为一个映射对象存储其中(一对一对的情侣)

 

Collection接口:

是List、Set、Queue接口的父接口

定义了可用于操作List、Set、Queue的方法(增删改查)

(具体方法可以参考JDK的API文档)

因为文件较大无法上传,想要了解的朋友可以联系我,也可以直接上网自行百度

List接口及其实现类——ArraysList

List是元素有序并且可以重复的集合,被称为序列

List可以精确的控制每一个元素的插入位置,或者删除某一个位置元素

ArraysList--数组序列,是List的一个重要实现类

ArraysList的底层是由数组实现的

 

 

下面有一个具体的实例来应用一下List

实现功能——模拟学生选课功能

1 选择课程(往集合中添加课程)

2 删除所选的某门课程(删除集合中的元素)

3 查看所选的课程

4 修改所选的课程

 

学生选课——创建学生类和课程类

import java.util.Set;  //这两个包不要忘记添加哦
import java.util.HashSet;
// 学生类
public class Student {

public String id;
public String name;

public Set courses;
// 学生类的构造函数(含参构造器)
public Student(String id, String name){
this.id = id;
this.name = name;
// 初始化courses属性 Set是一个接口不能直接初始化
// 所以这里用HashSet初始化
this.courses = new HashSet();
}
}

// 课程类
public class Course {

public String id;
public String name;

// 课程类的构造函数(含参构造器)
public Course(String id ,String name){
this.id = id;
this.name = name;
}
}

学生选课——添加课程

首先要将备选课程添加至List容器中(创建ListTest类)

  3 import java.sql.Array;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.Iterator;
7 import java.util.List;
8
9 public class ListTest {
10 // 备选课程
11 public List coursesToSelect;
12
13 // ListTest类的构造方法
14 public ListTest(){
15 // List是一个接口不能直接初始化 使用List接口下的ArrayList类
16 this.coursesToSelect = new ArrayList();
17 }
18
19 // 用于往coursesToSelect中添加备选课程
20 public void testAdd(){
21 // 创建一个课程对象,并通过调用add方法,添加到备选课程List中
22 Course cr1 = new Course("1","数据结构");
23 coursesToSelect.add(cr1);
24 /* 通过List的get方法取出元素,验证课程是否添加成功
25 * 由于对象存入集合都变成里object类型,取出时需要类型转换
26 * 由于这是添加的第一个课程信息所以下标为0
27 */
28 Course temp = (Course) coursesToSelect.get(0);
29 System.out.println("添加了课程:" + temp.id + temp.name );
30
31
32
33 /*
34 * List中还重载了另一个add方法 该方法不仅可以添加新元素,
35 * 而且可以指定添加的位置
36 */
37 Course cr2 = new Course("2","C语言");
38 coursesToSelect.add(0,cr2); // 指定添加位置为0,原位置上的元素被挤下去
39 Course temp2 = (Course) coursesToSelect.get(0); // 类型强转
40 System.out.println("添加了课程:" + temp2.id + temp2.name );
41
42
43 /*
44 * 在添加课程过程中,如果传递的位置参数大于现在的长度时(或者数组下标小于0)
45 * 会报(IndexOutOfBoundsException)异常
46 */
47 // Course cr3 = new Course("3","概率论");
48 // coursesToSelect.add(4, cr3);
49 // Course temp3 = (Course) coursesToSelect.get(0);
50 // System.out.println("添加了课程" + temp3.id + temp3.name);
51
52
53 /*
54 * 除了add方法 还有另外两种方法可以实现往List中添加课程
55 * addAll方法 首先将course数组通过Arrays的asList方法转变为List
56 * 1 直接利用addAll添加课程 2 通过传递一个位置参数将课程添加至指定位置
57 */
58 Course[] course = {new Course("4","离散数学"), new Course("5","汇编语言")};
59 coursesToSelect.addAll(Arrays.asList(course));
60 Course temp4 = (Course) coursesToSelect.get(2);
61 Course temp5 = (Course) coursesToSelect.get(3);
62 System.out.println("添加了两门课程:" + temp4.id + temp4.name +
63 temp5.id + temp5.name);
64
65 Course[] course2 = {new Course("6","高等数学"), new Course("6","大学英语")};
66 coursesToSelect.addAll(2,Arrays.asList(course2));
67 Course temp6 = (Course) coursesToSelect.get(2);
68 Course temp7 = (Course) coursesToSelect.get(3);
69 System.out.println("添加了两门课程:" + temp6.id + temp6.name +
70 temp7.id + temp7.name);
71
72
73 // List中的元素可以重复 以下是代码演示
74 // coursesToSelect.add(cr1);
75 // Course temp0 = (Course) coursesToSelect.get(6);
76 // System.out.println("添加了课程:" + temp0.id + temp0.name );
77
78 }
79
80
81 // 取得List中的元素的方法
82 public void testGet(){
83 System.out.println();
84 int size = coursesToSelect.size(); // 取得List中的元素个数
85 System.out.println("有如下课程待选:");
86 for (int i = 0; i < size; i ++){
87 Course cr = (Course) coursesToSelect.get(i);
88 System.out.println("课程:"+cr.id + cr.name);
89 }
90 }
91
92
93 /*
94 * 通过迭代器来遍历List
95 * 迭代器只用来遍历集合中元素,本身不具备存储功能
96 * 还有另一种写法(简便版) ForEach
97 */
98 public void testIterator(){
99 System.out.println();
100 // 通过集合的iterator方法,取得迭代器的实例
101 Iterator it = coursesToSelect.iterator();
102 System.out.println("有如下课程待选(通过迭代器访问):");
103 while (it.hasNext()){
104 Course cr = (Course) it.next();
105 System.out.println("课程:"+cr.id + cr.name);
106 }
107 }
108 // 通过for each 方法访问集合元素
109 public void testForEach(){
110 System.out.println();
111 System.out.println("有如下课程可选(通过for each访问):");
112 for (Object obj : coursesToSelect){
113 Course cr = (Course)obj;
114 System.out.println("课程:" + cr.id + cr.name);
115 }
116 }
117
118 /*
119 * 修改List中的元素
120 * 利用List中的Set方法修改元素值
121 * set中有两个参数 位置参数 更改的值
122 */
123 public void testModify(){
124 coursesToSelect.set(4, new Course("7","毛概"));
125 }
126
127
128 // 删除List中的元素 有两种方法法
129 public void testRemove (){
130 System.out.println();
131 Course cr = (Course) coursesToSelect.get(4);
132 System.out.println("我是课程:"+cr.id + cr.name+"我即将被删除");
133 coursesToSelect.remove(cr);
134 // 也可以直接删除指定位置上的元素 效果一样
135 // coursesToSelect.remove(4);
136 System.out.println("成功删除课程!");
137 testForEach();
138
139 // System.out.println("即将删除4位置和5位置上的元素!");
140 // Course[] courses = {(Course) coursesToSelect.get(3),(Course) coursesToSelect.get(4)};
141 // coursesToSelect.removeAll(Arrays.asList(courses));
142 // System.out.println("成功删除课程!");
143 // testForEach();
144 }
145
146
147 /*
148 * 前面我们所添加的都是一些正常的课程信息(课程id,课程name)
149 * 但是当我们添加了一些“不正常的信息”时 会怎么样嘞?
150 * 下面我们来试验一下:
151 * 往List中添加一些奇怪的东西
152 * 运行之后你会发现 程序并没有add成功
153 * 并且抛出了一个 ClassCastException异常(String类型不能被强转为course类型)
154 *
155 *
156 * 有木有办法控制我们往某一个集合或者List中添加元素的类型嘞?
157 * YES 这里我们可以利用 “泛型” 关于泛型的概念在下面会有介绍
158 */
159
160 // public void testType(){
161 // System.out.println("能否往List中添加一些奇怪的东西呢?");
162 // coursesToSelect.add("我不是课程 我只是一个字符串!");
163 // }
164
165
166 public static void main (String[] args){
167 // 创建ListTest 对象的实例
168 ListTest lt = new ListTest();
169 lt.testAdd();
170 lt.testGet();
171 lt.testIterator();
172 lt.testForEach();
173 lt.testModify();
174 lt.testForEach();
175 lt.testRemove();
176 //lt.testType();
177 lt.testForEach();
178 }
179
180 }
Java 之集合框架 上(9)Java 之集合框架 上(9)
添加了课程:1数据结构
添加了课程:2C语言
添加了两门课程:4离散数学5汇编语言
添加了两门课程:6高等数学6大学英语

有如下课程待选:
课程:2C语言
课程:1数据结构
课程:6高等数学
课程:6大学英语
课程:4离散数学
课程:5汇编语言

有如下课程待选(通过迭代器访问):
课程:2C语言
课程:1数据结构
课程:6高等数学
课程:6大学英语
课程:4离散数学
课程:5汇编语言

有如下课程可选(通过for each访问):
课程:2C语言
课程:1数据结构
课程:6高等数学
课程:6大学英语
课程:4离散数学
课程:5汇编语言

有如下课程可选(通过for each访问):
课程:2C语言
课程:1数据结构
课程:6高等数学
课程:6大学英语
课程:7毛概
课程:5汇编语言

我是课程:7毛概我即将被删除
成功删除课程!

有如下课程可选(通过for each访问):
课程:2C语言
课程:1数据结构
课程:6高等数学
课程:6大学英语
课程:5汇编语言

有如下课程可选(通过for each访问):
课程:2C语言
课程:1数据结构
课程:6高等数学
课程:6大学英语
课程:5汇编语言
Output

 

泛型:

用于控制往某个集合或者List中添加元素的类型

集合中的元素,可以是任意类型的对象(对象的引用)

如果把某一个对象放入到集合,则会忽略他的类型而把它当做Object处理

泛型则是规定了某个集合只可以存放特定类型的对象,并且会在编译过程中进行类型检查。可以直接按指定类型获取集合元素

注意:

泛型集合中的限定类型不能使用基本数据类型。

可以通过使用 包装类 限定允许存入的基本数据类型。

 1    /*
2 * ChildCourse 继承Course类型 而Course中我们定义了一个含参构造器
3 * 所以编译器就不会再自动添加一个隐式的无参构造器
4 * 但是在Course的子类(该类)中必须要调用父类的隐式构造器
5 * 所以这里会提示错误
6 * 这是我们只需要再course类中手动添加一个无参构造器即可
7 */
8 public class ChildCourse extends Course {
9
10 /*
11 * ChildCourse无需再添加任何属性
12 * 所有的属性均继承Course类型的属性即可
13 */
14 }
15
16 import java.util.ArrayList;
17 import java.util.List;
18
19 public class TestGeneric {
20
21 // 带有泛型——Course,的List类型属性
22 public List<Course> courses;
23
24 public TestGeneric(){ // 因为指定了泛型 所以这里要加上<Course>
25 this.courses = new ArrayList<Course>(); // 后面的圆括号表示调用了构造方法
26 }
27
28 // 测试添加
29 public void testAdd(){
30 Course cr1 = new Course("1","大学语文");
31 courses.add(cr1);
32 /*
33 * 当添加的信息不正确时 编译器会直接报错
34 * 泛型集合中,不能添加泛型规定的类型及其子类型以外的对象,否则会报错
35 */
36 //courses.add("能否添加一些奇怪的东西?");
37 Course cr2 = new Course("2","Java基础教程");
38 courses.add(cr2);
39 }
40
41 // 测试循环遍历
42 public void testForEach(){
43 // 这里的course在编译的时候已经规定了泛型,所以这里不用再把当做Object类型转换
44 for (Course cr:courses){
45 System.out.println(cr.id + cr.name);
46
47 }
48 }
49
50 // 测试泛型集合可以添加泛型的子类型的塑像实例
51 public void testChild (){
52 ChildCourse ccr = new ChildCourse();
53 ccr.id = "3";
54 ccr.name = "我是子类型的课程对象实例~~";
55 courses.add(ccr);
56 }
57
58 /*
59 * 注意:
60 * 泛型集合中的限定类型不能使用基本数据类型。
61 * 可以通过使用 包装类 限定允许存入的基本数据类型。
62 */
63 public void testBasicType(){
64 // 这里如果写成int的话编译器会报错,所以要用Integer
65 List<Integer> list = new ArrayList<Integer>();
66 list.add(1); // 这里的1(基本类型) 被强制转换成了int的包装类Integer,然后被加入到list中
67 System.out.println("基本类型必须使用包装类作为泛型" + list.get(0));
68 }
69
70
71 public static void main(String[] args) {
72
73 TestGeneric tg = new TestGeneric();
74 tg.testAdd();
75 tg.testForEach();
76
77 tg.testChild();
78 tg.testForEach();
79
80 tg.testBasicType();
81 }
82
83 }
Java 之集合框架 上(9)Java 之集合框架 上(9)
1大学语文
2Java基础教程
1大学语文
2Java基础教程
3我是子类型的课程对象实例
~~
基本类型必须使用包装类作为泛型1
Output

 

 

学生选课——通过set集合管理课程

 

Set接口及其实现类——HashSet

 

Set是元素无序并且不可以不可以重复的集合,被称为集

 

HashSet——哈希集,是set的一个重要实现类

 

Set中没有提供像list中的set()方法(修改指定位置上的元素):list——有序    set——无序

 

 

 

下面通过实例来形象的说明一下吧

案例功能说明:

  1 提供备选课程

  2 创建学生对象,并给该学生添加三门课程(添加到学生的courses——set类型的属性中)

    显示备选课程

    循环三次,每次输入课程ID

    往学生的courses属性中添加与输入的ID匹配的课程

    输出学生选择的课程

  1 import java.util.ArrayList;
2 import java.util.Arrays;
3 import java.util.List;
4 import java.util.Scanner;
5 public class SetTest {
6
7 /*
8 * 在前面的student类中 我们定义了一个set类型的属性
9 * 在这里 我们需要将上面student类中的set属性加一个泛型
10 */
11
12 public List<Course> coursesToSelect;
13
14 public SetTest(){
15 coursesToSelect = new ArrayList<Course>();
16
17
18 }
19
20
21 /*
22 * 这里我们可以小小的偷个懒,将刚才写过的testAdd直接复制过来
23 * 同时将所有多余的打印输出注释掉
24 */
25 // 用于往coursesToSelect中添加备选课程
26 public void testAdd(){
27 // 创建一个课程对象,并通过调用add方法,添加到备选课程List中
28 Course cr1 = new Course("1","数据结构");
29 coursesToSelect.add(cr1);
30 /* 通过List的get方法取出元素,验证课程是否添加成功
31 * 由于对象存入集合都变成里object类型,取出时需要类型转换
32 * 由于这是添加的第一个课程信息所以下标为0
33 */
34 Course temp = (Course) coursesToSelect.get(0);
35 //System.out.println("添加了课程:" + temp.id + temp.name );
36
37
38
39 /*
40 * List中还重载了另一个add方法 该方法不仅可以添加新元素,
41 * 而且可以指定添加的位置
42 */
43 Course cr2 = new Course("2","C语言");
44 coursesToSelect.add(0,cr2); // 指定添加位置为0,原位置上的元素被挤下去
45 Course temp2 = (Course) coursesToSelect.get(0); // 类型强转
46 //System.out.println("添加了课程:" + temp2.id + temp2.name );
47
48
49 /*
50 * 在添加课程过程中,如果传递的位置参数大于现在的长度时(或者数组下标小于0)
51 * 会报(IndexOutOfBoundsException)异常
52 */
53 // Course cr3 = new Course("3","概率论");
54 // coursesToSelect.add(4, cr3);
55 // Course temp3 = (Course) coursesToSelect.get(0);
56 // System.out.println("添加了课程" + temp3.id + temp3.name);
57
58
59 /*
60 * 除了add方法 还有另外两种方法可以实现往List中添加课程
61 * addAll方法 首先将course数组通过Arrays的asList方法转变为List
62 * 1 直接利用addAll添加课程 2 通过传递一个位置参数将课程添加至指定位置
63 */
64 Course[] course = {new Course("4","离散数学"), new Course("5","汇编语言")};
65 coursesToSelect.addAll(Arrays.asList(course));
66 Course temp4 = (Course) coursesToSelect.get(2);
67 Course temp5 = (Course) coursesToSelect.get(3);
68 //System.out.println("添加了两门课程:" + temp4.id + temp4.name +
69 // temp5.id + temp5.name);
70
71 Course[] course2 = {new Course("6","高等数学"), new Course("6","大学英语")};
72 coursesToSelect.addAll(2,Arrays.asList(course2));
73 Course temp6 = (Course) coursesToSelect.get(2);
74 Course temp7 = (Course) coursesToSelect.get(3);
75 //System.out.println("添加了两门课程:" + temp6.id + temp6.name +
76 // temp7.id + temp7.name);
77
78
79 // List中的元素可以重复 以下是代码演示
80 // coursesToSelect.add(cr1);
81 // Course temp0 = (Course) coursesToSelect.get(6);
82 // System.out.println("添加了课程:" + temp0.id + temp0.name );
83
84 }
85
86
87 // 通过for each 方法访问集合元素
88 public void testForEach(){
89 System.out.println();
90 System.out.println("有如下课程可选(通过for each访问):");
91 for (Object obj : coursesToSelect){
92 Course cr = (Course)obj;
93 System.out.println("课程:" + cr.id + cr.name);
94 }
95 }
96
97
98
99 public static void main(String[] args) {
100
101 SetTest st = new SetTest();
102 st.testAdd();
103 st.testForEach();
104
105 // 创建一个学生对象
106 Student student = new Student("1","小明");
107 System.out.println("欢迎学生:"+ student.name + "选课");
108 // 创建一个Scanner ,用来接收从键盘输入的课程ID
109 Scanner console = new Scanner(System.in);
110
111 /*
112 * 输入三个ID 选三门课
113 * 将每一个ID 跟coursesToSelect中的每一个课程对象比较
114 * 如果ID相等的情况下,就将该课程对象添加到小明的选课信息中
115 */
116 for (int i = 0; i < 3; i ++){
117 System.out.println("请输入课程ID:");
118 String courseId = console.next();
119 for (Course cr:st.coursesToSelect){
120 if (cr.id.equals(courseId)){
121 student.courses.add(cr);
122 student.courses.add(cr); //验证set中元素不可重复
123 // set 中添加某个对象,无论添加多少次最终只会保留一个该对象(的引用)
124 }
125 }
126 }
127 st.testForEachForSet(student);
128 }
129
130 public void testForEachForSet(Student student){
131
132 //验证set中元素不可重复
133 System.out.println("共选择了:" + student.courses.size() + "门课程");
134
135 /*
136 * 打印输出,学生所选的课程!
137 * 这里需要说明一点 循环遍历set中的元素 只能用佛reach方法或者
138 * iterator方法,而不能像list那样调用get()方法
139 * 这是因为set本身是无序的,所以不可能去查询指定位置上的元素
140 * 只能通过循环迭代出来 由于它是无序的所以每一次他的结果都是不太一样的
141 */
142
143 for (Course cr:student.courses){
144 System.out.println("选择了课程:" + cr.id + cr.name);
145
146 }
147 }
148 }

 

PS~ 如有手误  欢迎指出