集合的数学定义:集合是指具有某种特定性质的具体的或抽象的对象汇总而成的集体。其中,构成集合的这些对象则称为该集合的元素,来源百度百科
JAVA中集合定义:JAVA中集合是一种集合类,是一种工具,类似于容器,可以存储任意数量的具有共同属性的对象
集合的作用:在类的内部对数据进行组织;简单而快速的搜索大量条目;有的集合接口,提供了一些列排列有序的元素,并且可以在序列中间快速的插入或删除有关元素;有的集合接口提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型。
集合与数组:
数组的长度是固定的,而集合的长度能在使用中进行动态扩展;数组只能通过数组下标访问其中的元素,数组下标只能是整型,类型固定,一般情况难以知晓元素在数组中的位置,因此只能通过遍历数组进行筛选,当数据量过于庞大时,十分不便。而有的集合提供了映射关系,可以根据任意类型的关键字去寻找一一对应的对象从而很方便的实现查找具体对象的功能。
其中最常用的有ArrayList
,LinkedList
,HashSet
,HashMap
。
Collection 与 Map 对应关系示例于下图,由于 Collection 的存储是单个出现,而 Map 是利用键值对成对出现,因此 Collection 可以看成是单身宿舍,Map 则是成对的夫妇。
Collection接口
◈List、Set和Queue接口的父接口
◈定义了可用于操作List、Set和Queue的方法——增删改查
List接口及其实现类——ArrayList
◈List是元素有序并且可以重复的集合,称为序列
◈List可以精确控制每个元素的插入位置,或删除某个位置的元素
◈ArrayList——数组序列,是List的一个重要实现类
◈ArrayList底层由数组实现
实现功能——模拟学生选课功能
◈选择课程(往集合中添加课程)
◈删除所选的某门课程(删除集合中的元素)
◈查看所选课程
◈修改所选课程
Course.java
package com.imooc.collection;
/**
* 课程类
* @author Administrator
*/
public class Course {
public String id;
public String name;
public Course(String id, String name){
this.id = id;
this.name = name;
}
/**
* 添加一个无参构造器
*/
public Course(){
}
}
ListTest.java
package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* 备选课程类
* 用于存放备选课程的List
* @author Administrator
*/
public class ListTest {
public List coursesToSelect;
public ListTest(){
//接口不能直接实例化,必须依赖接口对应的实现类去实例化对象
//使用List接口的实现类ArrayList去实现List接口
this.coursesToSelect = new ArrayList();
}
/**
* 用于往coursesToSelect中添加备选课程
*/
public void testAdd(){
//创建一个课程对象,并通过调用add方法,添加到备选课程List中
Course cr1 = new Course("1", "数据结构");
coursesToSelect.add(cr1);
//对象存入集合都变成Object类型,取出时需要类型转换
Course temp1 = (Course) coursesToSelect.get(0);
System.out.println("添加了课程:" + temp1.id + ":" + temp1.name);
Course cr2 = new Course("2", "C语言");
coursesToSelect.add(0, cr2);
Course temp2 = (Course) coursesToSelect.get(0);
System.out.println("添加了课程:" + temp2.id + ":" + temp2.name);
//重复添加,表明List中的元素是有序且可以重复的【【
coursesToSelect.add(cr1);
Course temp0 = (Course) coursesToSelect.get(2);
System.out.println("添加了课程:" + temp0.id + ":" + temp0.name);
//以下方法会抛出数组下标越界异常
// Course cr3 = new Course("3", "test");
// courseToSelect.add(512, cr3);
//创建课程数组,内部存储一些课程类
Course[] course1 = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
//利用Arrays.asList讲数组转变为一个List
coursesToSelect.addAll(Arrays.asList(course1));
Course temp3 = (Course)coursesToSelect.get(3);
Course temp4 = (Course)coursesToSelect.get(4);
System.out.println("添加了两门课程:" + temp3.id + ":" + temp3.name +
";" + temp4.id + ":" + temp4.name);
Course[] course2 = {new Course("5", "高等数学"), new Course("6", "概率论与数理统计")};
coursesToSelect.addAll(2, Arrays.asList(course2));
Course temp5 = (Course)coursesToSelect.get(2);
Course temp6 = (Course)coursesToSelect.get(3);
System.out.println("添加了两门课程:" + temp5.id + ":" + temp5.name +
";" + temp6.id + ":" + temp6.name);
}
/**
* 取得List中的元素的方法
*/
public void testGet(){
//利用List中的size方法获得列表的长度
int size = coursesToSelect.size();
System.out.println("有如下课程待选:");
for(int i=0; i < size; i++){
Course cr = (Course)coursesToSelect.get(i);
System.out.println("课程:" + cr.id + ":" + cr.name);
}
}
/**
* 通过迭代器来遍历List
*/
public void testIterator(){
//通过集合的iterator方法,取得迭代器的实例
Iterator it = coursesToSelect.iterator();
System.out.println("有如下课程待选(通过迭代器访问):");
//通过hasNext方法判断是否还有元素,通过next方法获取下一元素
while(it.hasNext()){
Course cr = (Course)it.next();
System.out.println("课程:" + cr.id + ":" + cr.name);
}
}
/**
* 通过for each方法访问集合元素
*/
public void testForEach(){
System.out.println("有如下课程待选(通过for each访问):");
for(Object obj:coursesToSelect){
Course cr = (Course)obj;
System.out.println("课程:" + cr.id + ":" + cr.name);
}
}
/**
* 修改List中的元素
*/
public void testModify(){
System.out.println("********修改课程********");
coursesToSelect.set(4, new Course("7", "毛泽东概论"));
}
/**
* 删除List中的元素
*/
public void testRemove(){
// Course cr = (Course)courseToSelect.get(4);
// System.out.println("我是课程:" + cr.id + ":" + cr.name + ",我即将被删除");
// courseToSelect.remove(cr);
System.out.println("********即将删除4位置和5位置上的课程********");
Course[] courses = {(Course)coursesToSelect.get(4), (Course)coursesToSelect.get(5)};
coursesToSelect.removeAll(Arrays.asList(courses));
// System.out.println("********即将删除4位置上的课程********");
// courseToSelect.remove(4);
System.out.println("成功删除课程!");
testForEach();
}
/**
* 往List中添加一些奇怪的东西
*/
public void testType(){
System.out.println("能否往List中添加一些奇怪的方法呢!?");
coursesToSelect.add("我不是课程,我只是一个无辜的字符串");
}
/**
* main方法
* @param args
*/
public static void main(String[] args){
ListTest lt = new ListTest();
lt.testAdd();
//添加非Course类型对象会报错
//采用try-catch-finally捕获仍然会报错
//原因是执行try时已经向List中添加了字符串且并不会报错
//执行后面的程序时,取到的是字符串而不是Course类型导致后面执行类型强转报错
/**
* Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class com.imooc.collection.Course (java.lang.String is in module java.base of loader 'bootstrap'; com.imooc.collection.Course is in unnamed module of loader 'app')
* at com.imooc.collection.ListTest.testGet(ListTest.java:74)
* at com.imooc.collection.ListTest.main(ListTest.java:152)
*/
lt.testGet();
lt.testIterator();
lt.testForEach();
lt.testModify();
lt.testForEach();
lt.testRemove();
}
}
添加了课程:1:数据结构
添加了课程:2:C语言
添加了课程:1:数据结构
添加了两门课程:3:离散数学;4:汇编语言
添加了两门课程:5:高等数学;6:概率论与数理统计
有如下课程待选:
课程:2:C语言
课程:1:数据结构
课程:5:高等数学
课程:6:概率论与数理统计
课程:1:数据结构
课程:3:离散数学
课程:4:汇编语言
有如下课程待选(通过迭代器访问):
课程:2:C语言
课程:1:数据结构
课程:5:高等数学
课程:6:概率论与数理统计
课程:1:数据结构
课程:3:离散数学
课程:4:汇编语言
有如下课程待选(通过for each访问):
课程:2:C语言
课程:1:数据结构
课程:5:高等数学
课程:6:概率论与数理统计
课程:1:数据结构
课程:3:离散数学
课程:4:汇编语言
********修改课程********
有如下课程待选(通过for each访问):
课程:2:C语言
课程:1:数据结构
课程:5:高等数学
课程:6:概率论与数理统计
课程:7:毛泽东概论
课程:3:离散数学
课程:4:汇编语言
********即将删除4位置和5位置上的课程********
成功删除课程!
有如下课程待选(通过for each访问):
课程:2:C语言
课程:1:数据结构
课程:5:高等数学
课程:6:概率论与数理统计
课程:4:汇编语言
Process finished with exit code 0
泛型:集合中的元素可以是任意类型的对象(对象的引用),如果把某个对象放入集合,则会忽略它的类型,而仅仅将其作为Object类处理,因此在取出访问时需要强制转换类型。泛型则是规定了某个集合只可以存放特定类型的对象,并且在编译期间,编译器会对其进行类型检查。
简单来说,增加了泛型的集合就是“物以类聚,非我族类,其心必异”,就像刚出生的婴儿,本应该喂养母乳,如果给其喂入市面上的奶粉,则会出现各种各样的问题。
注意:
◈泛型集合中的限定类型不能使用基本数据类型
◈泛型集合可以添加泛型的子类型的对象实例
◈可以通过使用包装类限定允许存入的基本数据类型
◈int
→Integer
、long
→Long
、boolean
→Boolean
Course.java
与上个示例相同
package com.imooc.collection;
/**
* 课程类
* @author Administrator
*/
public class Course {
public String id;
public String name;
public Course(String id, String name){
this.id = id;
this.name = name;
}
/**
* 添加一个无参构造器
*/
public Course(){
}
}
ChildCourse.java
继承于Course
package com.imooc.collection;
public class ChildCourse extends Course {
}
TestGeneric.java
package com.imooc.collection;
import java.util.ArrayList;
import java.util.List;
public class TestGeneric {
/**
* 带有泛型——Course的List类型属性
*/
public List<Course> courses;
//在实例化时,ArrayList也需要添加泛型
public TestGeneric(){
this.courses = new ArrayList<Course>();
}
/**
* 测试添加
*/
public void testAdd(){
Course cr1 = new Course("1", "大学语文");
courses.add(cr1);
//泛型集合中,不能添加泛型规定的类型及其子类型以外的对象,否则会报错!
// courses.add("能否添加一些奇怪的东西呢?");
Course cr2 = new Course("2", "Java基础");
courses.add(cr2);
}
/**
* 测试遍历循环
*/
public void testForEach(){
for (Course cr:courses){
System.out.println(cr.id + ":" + cr.name);
}
}
/**
* 泛型集合可以添加泛型的子类型的对象实例
*/
public void testChild(){
ChildCourse ccr = new ChildCourse();
ccr.id = "3";
ccr.name = "我是子类型的课程对象实例";
courses.add(ccr);
}
/**
* 泛型不能使用基本类型
*/
public void testBasicType(){
//泛型不能使用基本类型,必须使用其包装类
// List list = new ArrayList();
List<Integer> list = new ArrayList<Integer>();
//自动装箱,将int类型1装箱成包装类Integer
list.add(1);
System.out.println("基本类型必须使用包装类作为泛型!" + list.get(0));
}
/**
* @param args
*/
public static void main(String[] args){
TestGeneric tg = new TestGeneric();
tg.testAdd();
tg.testForEach();
tg.testChild();
tg.testForEach();
tg.testBasicType();
}
}
1:大学语文
2:Java基础
1:大学语文
2:Java基础
3:我是子类型的课程对象实例
基本类型必须使用包装类作为泛型!1
Set接口及其实现类——HashSet
◈Set是元素无序并且不可以重复的集合,被称为集
◈HashSet——哈希集,是Set的一个重要实现类
◈Set中可以添加空对象null
◈在Set遍历输出时只能使用foreach与iterator方法,不能使用List中的get()方法。因为Set是无序的,不可能去查询指定的索引位置上的具体的元素
示例实现功能
◈提供备选课程
◈创建学生对象,并给该学生添加三门课程(添加在学生的courses——Set类型的属性中)
◈显示备选课程
◈循环三次,每次输入课程ID
◈往学生的courses属性中添加与输入的ID匹配的课程
◈输出学生选择的课程
Student.java
package com.imooc.collection;
import java.util.HashSet;
import java.util.Set;
/**
* 学生类
* @author Administrator
*/
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;
//利用HashSet实现类实例化courses
this.courses = new HashSet<Course>();
}
}
SetTest.java
package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class SetTest {
//带有Course泛型的List
public List<Course> coursesToSelect;
public SetTest(){
coursesToSelect = new ArrayList<Course>();
}
/**
* 用于往coursesToSelect中添加备选课程
*/
public void testAdd(){
//创建一个课程对象,并通过调用add方法,添加到备选课程List中
Course cr1 = new Course("1", "数据结构");
coursesToSelect.add(cr1);
Course temp1 = coursesToSelect.get(0);
Course cr2 = new Course("2", "C语言");
coursesToSelect.add(0, cr2);
Course temp2 = coursesToSelect.get(0);
Course[] course1 = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
coursesToSelect.addAll(Arrays.asList(course1));
Course temp3 = coursesToSelect.get(2);
Course temp4 = coursesToSelect.get(3);
Course[] course2 = {new Course("5", "高等数学"), new Course("6", "概率论与数理统计")};
coursesToSelect.addAll(2, Arrays.asList(course2));
Course temp5 = coursesToSelect.get(2);
Course temp6 = coursesToSelect.get(3);
}
/**
* 通过for each方法访问集合元素
*/
public void testForEach(){
System.out.println("有如下课程待选(通过for each访问):");
for(Course course:coursesToSelect){
System.out.println("课程:" + course.id + ":" + course.name);
}
}
/**
* @param args
*/
public static void main(String[] args){
SetTest st = new SetTest();
st.testAdd();
st.testForEach();
//创建一个学生对象
Student student = new Student("1", "小明");
System.out.println("欢迎学生:" + student.name + "选课!");
//创建一个Scanner对象,用来接收从键盘输入的课程ID
Scanner console = new Scanner(System.in);
for(int i = 0;i < 3;i++){
System.out.println("请输入课程ID");
String courseId = console.next();
for(Course cr:st.coursesToSelect){
if(cr.id.equals(courseId)){
student.courses.add(cr);
/**
* Set中,添加某个对象,无论添加多少次,
* 最终只会保留一个该对象(的引用),
* 并且,保留的是第一次添加的哪一个,
* Set中可以添加空对象null
*/
// student.courses.add(null);
// student.courses.add(cr);
}
}
}
st.testForEachForSet(student);
}
public void testForEachForSet(Student student){
//打印输出,学生所选的课程!
//验证Set的容量
System.out.println("共选择了:" + student.courses.size() + "门课程");
for(Course cr:student.courses){
System.out.println("选择了课程:" + cr.id + ":" + cr.name);
}
}
}
课程:2:C语言
课程:1:数据结构
课程:5:高等数学
课程:6:概率论与数理统计
课程:3:离散数学
课程:4:汇编语言
欢迎学生:小明选课!
请输入课程ID
2
请输入课程ID
3
请输入课程ID
4
共选择了:3门课程
选择了课程:3:离散数学
选择了课程:2:C语言
选择了课程:4:汇编语言
Map接口:
◈Map提供了一种映射关系,其中的元素是以键值对(key-value
)的形式存储,key
与value
可以是任意类型的对象,能够实现根据key
快速查找value
◈Map中键值对以Entry类型的对象实例形式存在
◈键(key值)不可重复,value值可以
◈每个键最多只能映射到一个值
◈Map接口提供了分别返会key
值集合、value
值集合以及Entry
(键值对)集合的方法
◈Map支持泛型,形式如:Map
HashMap类:
◈HashMap是Map的一个重要实现类,也是最常用的,基于哈希表实现
◈HashMap中的Entry对象是无序排列的
◈key值和value值都可以为null,但是一个HashMap只能有一个key值为null的映射(key值不可重复)
示例实现功能
◈通过Map
进行学生信息管理,其中key为学生ID,value为学生对象
◈通过键盘输入学生信息
◈对集合中的学生信息进行增、删、改、查操作
Student.java
package com.imooc.collection;
import java.util.HashSet;
import java.util.Set;
/**
* 学生类
* @author Administrator
*/
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;
//利用HashSet实现类实例化courses
this.courses = new HashSet<Course>();
}
}
MapTest.java
package com.imooc.collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
public class MapTest {
/**
* 用来盛装学生类型的对象
*/
public Map<String, Student> students;
/**
* 在构造器中初始化students属性
*/
public MapTest(){
this.students = new HashMap<String, Student>();
}
/**
* 测试添加:输入学生ID,判断是否被占用
* 若未被占用,则输入姓名,创建学生对象,并且
* 添加到students中
*/
public void testPut(){
//创建一个Scanner对象,用来获取输入学生ID和姓名
Scanner console = new Scanner(System.in);
int i = 0;
while(i < 3){
System.out.println("请输入学生ID:");
String ID = console.next();
//判断ID是否被占用
Student st = students.get(ID);
if(st == null){
//提示输入学生姓名
System.out.println("请输入学生姓名:");
String name = console.next();
//创建新的学生对象
Student newStudent = new Student(ID, name);
//通过调用students的inputs方法,添加ID-学生映射
students.put(ID, newStudent);
System.out.println("成功添加学生:" + students.get(ID).name);
i++;
}else{
System.out.println("该学生ID已被占用!");
// continue;
}
}
}
/**
* 测试Map的keySet方法
*/
public void testKeySet(){
//通过keySet方法,返回Map中的所有“键”的Set集合
Set<String> keySet = students.keySet();
//取得students的容量
System.out.println("总共有:" + students.size() + "个学生!");
//遍历keySet,取得每一个键,再调用get方法取得每个键对应的value
for(String stuId:keySet){
Student st = students.get(stuId);
if(st != null)
System.out.println("学生:" + st.name);
}
}
/**
* 测试删除Map中的映射
*/
public void testRemove(){
//获取从键盘输入的待删除学生ID字符串
Scanner console = new Scanner(System.in);
while (true){
//提示输入待删除的学生的ID
System.out.println("请输入要删除的学生ID!");
String ID = console.next();
//判断该ID是否有对应的学生对象
Student st = students.get(ID);
if(st == null){
//提示输入的ID并不存在
System.out.println("该ID不存在!");
continue;
}
students.remove(ID);
System.out.println("成功删除学生:" + st.name);
break;
}
}
/**
* 通过entrySet方法来遍历Map
*/
public void testEntrySet(){
//通过entrySet方法,返回Map中的所有键值对
Set<Entry<String, Student>> entrySet = students.entrySet();
for(Entry<String, Student> entry:entrySet){
System.out.println("取得键:" + entry.getKey());
System.out.println("对应的值为:" + entry.getValue().name);
}
}
/**
* 利用put方法修改Map中的已有映射
*/
public void testModify(){
//提示输入要修改的学生ID
System.out.println("请输入要修改的学生ID:");
//创建一个Scanner对象,去获取从键盘上输入的学生ID字符串
Scanner console = new Scanner(System.in);
while(true){
//取得从键盘输入的学生ID
String stuID = console.next();
//从students中查找该学生ID对应的学生对象
Student student = students.get(stuID);
if(student == null){
System.out.println("该ID不存在!请重新输入!");
continue;
}
//提示当前对应的学生对象的姓名
System.out.println("当前该学生ID,所对应的学生为:" + student.name);
//提示输入新的学生姓名,来修改已有的映射
System.out.println("请输入新的学生姓名:");
String name = console.next();
Student newStudent = new Student(stuID, name);
students.put(stuID, newStudent);
System.out.println("修改成功!");
break;
}
}
/**
* main方法
* @param args
*/
public static void main(String[] args){
MapTest mt = new MapTest();
mt.testPut();
mt.testKeySet();
// mt.testRemove();
// mt.testEntrySet();
mt.testModify();
mt.testEntrySet();
}
}
请输入学生ID:
1
请输入学生姓名:
Tom
成功添加学生:Tom
请输入学生ID:
2
请输入学生姓名:
Jack
成功添加学生:Jack
请输入学生ID:
3
请输入学生姓名:
Quanhao Guo
成功添加学生:Quanhao
总共有:3个学生!
学生:Tom
学生:Jack
学生:Quanhao
请输入要修改的学生ID:
4
该ID不存在!请重新输入!
3
当前该学生ID,所对应的学生为:Quanhao
请输入新的学生姓名:
HaoHao
修改成功!
取得键:1
对应的值为:Tom
取得键:2
对应的值为:Jack
取得键:3
对应的值为:HaoHao
问题思考:
◈在课程序列中,判断是否包含某门或者某几门课程——contains
/containsAll
方法
◈在包含某门课程的序列中,如何判断该课程的索引位置——indexOf
方法
◈在学生映射表中,判断是否包含某个学生ID——contains
/containsAll
方法
◈判断是否包含某个学生对象——contains
/containsAll
方法
◈对课程或学生对象,按照课程名或学生名,ID名进行排序——sort
方法
来源于JAVA11官网API
boolean contains(Object o)
true
。
更正式地说,返回true
当且仅当此列表包含至少一个元素e
,使得Objects.equals(o, e)
。
contains
在界面
Collection
o
- 要测试其在此列表中的存在的元素
true
如果此列表包含指定的元素
ClassCastException
- 如果指定元素的类型与此列表不兼容( optional )
NullPointerException
- 如果指定的元素为null且此列表不允许null元素( optional )
遍历List中每一个元素Element,然后调用每一个元素的equals方法与contains方法中的参数进行比较,如果有一个元素的equals方法返回true值,那么这个contains方法返回true值,否则返回false值
在Object
中除了定义equals
方法还定义了hashCode()
方法,其返回对象hash
码的值,在调用HashSet
中的contains
方法时,先调用每一个元素的hashCode()
方法来返回hash
码,如果hash
码相同的情况下再调用equals
方法去判断是否相等,只有这两个方法都相等的情况下,才认定HashSet
包含某个元素,因此在使用时往往需要重写equals()
方法和hashCode()
方法
boolean containsValue(Object value)
true
。
更正式地,返回true
当且仅当此映射包含的至少一个映射到一个值v
使得Objects.equals(value, v)
。
对于Map
接口的大多数实现,此操作可能需要在映射大小中线性时间。
value
- 要测试其在此映射中的存在的值
true
如果此映射将一个或多个键映射到指定的值
ClassCastException
- 如果该地图的数据类型不正确( optional )
NullPointerException
- 如果指定的值为null并且此映射不允许空值( optional )
与List
中的contains
方法一样,Map
中的containsValue
方法也需要调用每一个value
值得equals
方法去和参数对象进行比较,如果匹配成功,返会结果为true
。因此在使用时往往需要重写equals()
方法
从序列的第零个元素开始,依次循环,并且调用每一个元素的equals
方法去和参数对象进行比较,如果某一个元素的equals
方法返回值为true
,那么就把当前这个元素的索引位置作为结果返回。假如序列中有多个重复的元素,那么只返回重复元素第一次出现的那个索引位置。在List
中还定义了lastIndexOf
方法,它与indexOf
方法恰恰相反,它是返回某个元素最后一次出现的索引位置,它会从序列的队尾向对头去遍历每一个元素。如果没有获取到索引位置,它们都会返回-1
int indexOf(Object o)
i
如Objects.equals(o, get(i))
,如果没有这样的指数则返回-1。
o
- 要搜索的元素
ClassCastException
- 如果指定元素的类型与此列表不兼容( optional )
NullPointerException
- 如果指定的元素为null且此列表不允许null元素( optional )
int lastIndexOf(Object o)
i
如Objects.equals(o, get(i))
,如果没有这样的指数则为-1。
o
- 要搜索的元素
ClassCastException
- 如果指定元素的类型与此列表不兼容( optional )
NullPointerException
- 如果指定的元素为null且此列表不允许null元素( optional )
public static void sort(int[] a, int fromIndex, int toIndex)
fromIndex
,包容,到索引toIndex
,排斥。
如果是fromIndex == toIndex
, fromIndex == toIndex
排序的范围为空。
实施说明:排序算法是Vladimir Yaroslavskiy,Jon Bentley和Joshua Bloch的双枢轴快速算法。 该算法在许多数据集上提供O(n log(n))性能,导致其他快速排序降级为二次性能,并且通常比传统(单枢轴)Quicksort实现更快。
a
- 要排序的数组
fromIndex
- 要排序的第一个元素的索引(包括在内)
toIndex
- 要排序的最后一个元素的索引(不包括)
IllegalArgumentException
- 如果
fromIndex > toIndex
ArrayIndexOutOfBoundsException
- 如果是
fromIndex < 0
或
toIndex > a.length
排序操作,排序方法跟传统ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)相同
在JAVA中,两个对象想要进行排序,必须是可以比较的。我们使用Comparable这个接口表示某个对象是可以比较的。Comparable就是给对象定义了一个默认的排序规则。JAVA中提供了一个Comparator接口,用来定义临时的比较规则
Comparable接口 | Comparator接口——比较工具接口 |
---|---|
◈这个类的实例可以比较大小,可以进行自然排序 ◈自然排序是已定义的默认排序规则,例如字符串中的ASCII编码排序规则 ◈实现Comparable接口必须实现Comparable接口中定义的compareTo()方法。当两个实现了Comparable接口的类的实例进行比较的时候,就会调用compareTo()方法 ◈compareTo()方法返回正数表示大,负数表示小,0表示相等 |
◈用于定义临时比较规则,e不是默认比较规则 ◈实现Comparator接口必须实现compare()方法 ◈Comparator和Comparable都是JAVA集合框架的成员 |
ChildCourse.java
package com.imooc.collection;
public class ChildCourse extends Course {
}
CollectionsTest.java
package com.imooc.collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
* 将要完成:
* 1.通过Collections.sort()方法,对Integer泛型的List进行排序
* 2.对String泛型的List进行排序
* 3.对其它类型泛型的List进行排序,以Student为例
*/
public class CollectionsTest {
//定义全字符
public static final String SOURCES =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
/**
* 1.通过Collections.sort()方法,对Integer泛型的List进行排序
* 2.每条字符串的长度为10以内的随机整数
* 3.每条字符串的每个字符都为随机生成的字符,字符可以重复
* 4.每条随机字符串不可重复
*/
public void testSort1(){
List<Integer> integerList = new ArrayList<Integer>();
//插入10个100以内的不重复随机整数
Random random = new Random();
Integer k;
for(int i=0;i < 10; i++){
//让integerList中的随机整数不重复
do{
k = random.nextInt(100);
}while(integerList.contains(k));
integerList.add(k);
System.out.println("成功添加整数:" + k);
}
System.out.println("----------排序前----------");
for(Integer integer:integerList){
System.out.println("元素:" + integer);
}
Collections.sort(integerList);
System.out.println("----------排序后----------");
for(Integer integer:integerList){
System.out.println("元素:" + integer);
}
}
/**
* 2.对String泛型的List进行排序
* 创建String泛型的List,添加三个乱序的String元素,
* 调用sort方法,再次输出排序后的顺序
*/
public void testSort2(){
List<String> stringList = new ArrayList<String>();
stringList.add("microsoft");
stringList.add("google");
stringList.add("lenovo");
System.out.println("----------排序前----------");
for(String string:stringList){
System.out.println("元素:" + string);
}
Collections.sort(stringList);
System.out.println("----------排序后----------");
for(String string:stringList) {
System.out.println("元素:" + string);
}
}
/**
* 创建List之后,往其中添加十条随机字符串
* 每条字符串的长度为10以内的随机整数
* 每条字符串的每个字符都为随机生成的字符,字符可以重复
*/
public void testSort3(){
List<String> stringList = new ArrayList<String>();
Random random = new Random();
Integer k;
int i = 0;
//循环创建字符串直到出现10条字符串
while(true){
k = random.nextInt(10);
char[] text = new char[k];
for (int j = 0; j < k; j++) {
text[j] = SOURCES.charAt(random.nextInt(SOURCES.length()));
}
//满足10条字符串,跳出循环
if(i == 10)
break;
//出现重复字符串直接进入下一次循环,否则添加到List中
if(stringList.contains(new String(text)))
continue;
else {
i++;
stringList.add(new String(text));
}
}
System.out.println("---------排序前---------");
for(String string:stringList){
System.out.println("元素:" + string);
}
Collections.sort(stringList);
System.out.println("---------排序后---------");
for(String string:stringList) {
System.out.println("元素:" + string);
}
}
/**
* 3.对其它类型泛型的List进行排序,以Student为例
*/
public void testSort4(){
List<Student>studentList = new ArrayList<Student>();
Random random = new Random();
studentList.add(new Student(random.nextInt(1000) + "", "Mike"));
studentList.add(new Student(random.nextInt(1000) + "", "Angela"));
studentList.add(new Student(random.nextInt(1000) + "", "Lucy"));
studentList.add(new Student(10000+ "", "Beyonce"));
System.out.println("---------排序前---------");
for(Student student:studentList){
System.out.println("学生:" + student.id + ":" + student.name);
}
Collections.sort(studentList);
System.out.println("---------排序后---------");
for(Student student:studentList){
System.out.println("学生:" + student.id + ":" + student.name);
}
Collections.sort(studentList, new StudentComparator());
System.out.println("---------按照姓名排序后-------");
for(Student student:studentList){
System.out.println("学生:" + student.id + ":" + student.name);
}
}
/**
* @param args
*/
public static void main(String[] args){
CollectionsTest ct = new CollectionsTest();
// ct.testSort1();
// ct.testSort2();
// ct.testSort3();
ct.testSort4();
}
}
Course.java
package com.imooc.collection;
import java.util.Objects;
/**
* 课程类
* @author Administrator
*/
public class Course {
public String id;
public String name;
public Course(String id, String name){
this.id = id;
this.name = name;
}
/**
* 添加一个无参构造器
*/
public Course(){
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Course course = (Course) o;
return Objects.equals(name, course.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
// @Override
// public boolean equals(Object obj) {
// if(this == obj)
// return true;
// if(obj == null)
// return false;
// if(!(obj instanceof Course))
// return false;
// Course course = (Course) obj;
// if(this.name == null){
// if(course.name == null)
// return true;
// else
// return false;
// }else{
// if(this.name.equals(course.name))
// return true;
// else
// return false;
// }
// }
}
ListTest.java
package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* 备选课程类
* 用于存放备选课程的List
* @author Administrator
*/
public class ListTest {
public List coursesToSelect;
public ListTest(){
//接口不能直接实例化,必须依赖接口对应的实现类去实例化对象
//使用List接口的实现类ArrayList去实现List接口
this.coursesToSelect = new ArrayList();
}
/**
* 用于往coursesToSelect中添加备选课程
*/
public void testAdd(){
//创建一个课程对象,并通过调用add方法,添加到备选课程List中
Course cr1 = new Course("1", "数据结构");
coursesToSelect.add(cr1);
//对象存入集合都变成Object类型,取出时需要类型转换
Course temp1 = (Course) coursesToSelect.get(0);
System.out.println("添加了课程:" + temp1.id + ":" + temp1.name);
Course cr2 = new Course("2", "C语言");
coursesToSelect.add(0, cr2);
Course temp2 = (Course) coursesToSelect.get(0);
System.out.println("添加了课程:" + temp2.id + ":" + temp2.name);
//重复添加,表明List中的元素是有序且可以重复的【【
coursesToSelect.add(cr1);
Course temp0 = (Course) coursesToSelect.get(2);
System.out.println("添加了课程:" + temp0.id + ":" + temp0.name);
//以下方法会抛出数组下标越界异常
// Course cr3 = new Course("3", "test");
// courseToSelect.add(512, cr3);
//创建课程数组,内部存储一些课程类
Course[] course1 = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
//利用Arrays.asList讲数组转变为一个List
coursesToSelect.addAll(Arrays.asList(course1));
Course temp3 = (Course)coursesToSelect.get(3);
Course temp4 = (Course)coursesToSelect.get(4);
System.out.println("添加了两门课程:" + temp3.id + ":" + temp3.name +
";" + temp4.id + ":" + temp4.name);
Course[] course2 = {new Course("5", "高等数学"), new Course("6", "概率论与数理统计")};
coursesToSelect.addAll(2, Arrays.asList(course2));
Course temp5 = (Course)coursesToSelect.get(2);
Course temp6 = (Course)coursesToSelect.get(3);
System.out.println("添加了两门课程:" + temp5.id + ":" + temp5.name +
";" + temp6.id + ":" + temp6.name);
}
/**
* 取得List中的元素的方法
*/
public void testGet(){
//利用List中的size方法获得列表的长度
int size = coursesToSelect.size();
System.out.println("有如下课程待选:");
for(int i=0; i < size; i++){
Course cr = (Course)coursesToSelect.get(i);
System.out.println("课程:" + cr.id + ":" + cr.name);
}
}
/**
* 通过迭代器来遍历List
*/
public void testIterator(){
//通过集合的iterator方法,取得迭代器的实例
Iterator it = coursesToSelect.iterator();
System.out.println("有如下课程待选(通过迭代器访问):");
//通过hasNext方法判断是否还有元素,通过next方法获取下一元素
while(it.hasNext()){
Course cr = (Course)it.next();
System.out.println("课程:" + cr.id + ":" + cr.name);
}
}
/**
* 通过for each方法访问集合元素
*/
public void testForEach(){
System.out.println("有如下课程待选(通过for each访问):");
for(Object obj:coursesToSelect){
Course cr = (Course)obj;
System.out.println("课程:" + cr.id + ":" + cr.name);
}
}
/**
* 修改List中的元素
*/
public void testModify(){
System.out.println("********修改课程********");
coursesToSelect.set(4, new Course("7", "毛泽东概论"));
}
/**
* 删除List中的元素
*/
public void testRemove(){
// Course cr = (Course)courseToSelect.get(4);
// System.out.println("我是课程:" + cr.id + ":" + cr.name + ",我即将被删除");
// courseToSelect.remove(cr);
System.out.println("********即将删除4位置和5位置上的课程********");
Course[] courses = {(Course)coursesToSelect.get(4), (Course)coursesToSelect.get(5)};
coursesToSelect.removeAll(Arrays.asList(courses));
// System.out.println("********即将删除4位置上的课程********");
// courseToSelect.remove(4);
System.out.println("成功删除课程!");
testForEach();
}
/**
* 往List中添加一些奇怪的东西
*/
public void testType(){
System.out.println("能否往List中添加一些奇怪的方法呢!?");
coursesToSelect.add("我不是课程,我只是一个无辜的字符串");
}
/**
* main方法
* @param args
*/
public static void main(String[] args){
ListTest lt = new ListTest();
lt.testAdd();
//添加非Course类型对象会报错
//采用try-catch-finally捕获仍然会报错
//原因是执行try时已经向List中添加了字符串且并不会报错
//执行后面的程序时,取到的是字符串而不是Course类型导致后面执行类型强转报错
/**
* Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class com.imooc.collection.Course (java.lang.String is in module java.base of loader 'bootstrap'; com.imooc.collection.Course is in unnamed module of loader 'app')
* at com.imooc.collection.ListTest.testGet(ListTest.java:74)
* at com.imooc.collection.ListTest.main(ListTest.java:152)
*/
lt.testGet();
lt.testIterator();
lt.testForEach();
lt.testModify();
lt.testForEach();
lt.testRemove();
}
}
MapTest.java
package com.imooc.collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
public class MapTest {
/**
* 用来盛装学生类型的对象
*/
public Map<String, Student> students;
/**
* 在构造器中初始化students属性
*/
public MapTest(){
this.students = new HashMap<String, Student>();
}
/**
* 测试添加:输入学生ID,判断是否被占用
* 若未被占用,则输入姓名,创建学生对象,并且
* 添加到students中
*/
public void testPut(){
//创建一个Scanner对象,用来获取输入学生ID和姓名
Scanner console = new Scanner(System.in);
int i = 0;
while(i < 3){
System.out.println("请输入学生ID:");
String ID = console.next();
//判断ID是否被占用
Student st = students.get(ID);
if(st == null){
//提示输入学生姓名
System.out.println("请输入学生姓名:");
String name = console.next();
//创建新的学生对象
Student newStudent = new Student(ID, name);
//通过调用students的inputs方法,添加ID-学生映射
students.put(ID, newStudent);
System.out.println("成功添加学生:" + students.get(ID).name);
i++;
}else{
System.out.println("该学生ID已被占用!");
// continue;
}
}
}
/**
* 测试Map的keySet方法
*/
public void testKeySet(){
//通过keySet方法,返回Map中的所有“键”的Set集合
Set<String> keySet = students.keySet();
//取得students的容量
System.out.println("总共有:" + students.size() + "个学生!");
//遍历keySet,取得每一个键,再调用get方法取得每个键对应的value
for(String stuId:keySet){
Student st = students.get(stuId);
if(st != null)
System.out.println("学生:" + st.name);
}
}
/**
* 测试删除Map中的映射
*/
public void testRemove(){
//获取从键盘输入的待删除学生ID字符串
Scanner console = new Scanner(System.in);
while (true){
//提示输入待删除的学生的ID
System.out.println("请输入要删除的学生ID!");
String ID = console.next();
//判断该ID是否有对应的学生对象
Student st = students.get(ID);
if(st == null){
//提示输入的ID并不存在
System.out.println("该ID不存在!");
continue;
}
students.remove(ID);
System.out.println("成功删除学生:" + st.name);
break;
}
}
/**
* 通过entrySet方法来遍历Map
*/
public void testEntrySet(){
//通过entrySet方法,返回Map中的所有键值对
Set<Entry<String, Student>> entrySet = students.entrySet();
for(Entry<String, Student> entry:entrySet){
System.out.println("取得键:" + entry.getKey());
System.out.println("对应的值为:" + entry.getValue().name);
}
}
/**
* 利用put方法修改Map中的已有映射
*/
public void testModify(){
//提示输入要修改的学生ID
System.out.println("请输入要修改的学生ID:");
//创建一个Scanner对象,去获取从键盘上输入的学生ID字符串
Scanner console = new Scanner(System.in);
while(true){
//取得从键盘输入的学生ID
String stuID = console.next();
//从students中查找该学生ID对应的学生对象
Student student = students.get(stuID);
if(student == null){
System.out.println("该ID不存在!请重新输入!");
continue;
}
//提示当前对应的学生对象的姓名
System.out.println("当前该学生ID,所对应的学生为:" + student.name);
//提示输入新的学生姓名,来修改已有的映射
System.out.println("请输入新的学生姓名:");
String name = console.next();
Student newStudent = new Student(stuID, name);
students.put(stuID, newStudent);
System.out.println("修改成功!");
break;
}
}
/**
* 测试Map中,是否包含某个key值或者某个value值
*/
public void testContainsKeyOrValue(){
//提示输入学生ID
System.out.println("请输入要查询的学生ID:");
Scanner console = new Scanner(System.in);
String id = console.next();
//在Map中,用containsKey()方法,来判断是否包含某个key值
System.out.println("您输入的学生ID为:" + id + ",在学生映射表中是否存在:" +
students.containsKey(id));
if(students.containsKey(id))
System.out.println("对应的学生为:" + students.get(id).name);
//提示输入学生姓名
System.out.println("请输入要查询的学生姓名:");
String name = console.next();
//用containsValue()方法
if(students.containsValue(new Student(null, name)))
System.out.println("在学生映射表中,确实包含学生:" + name);
else
System.out.println("在学生映射表中不存在该学生!");
}
/**
* main方法
* @param args
*/
public static void main(String[] args){
MapTest mt = new MapTest();
mt.testPut();
mt.testKeySet();
// mt.testRemove();
// mt.testEntrySet();
// mt.testModify();
// mt.testEntrySet();
// mt.testContainsKeyOrValue();
}
}
SetTest.java
package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class SetTest {
//带有Course泛型的List
public List<Course> coursesToSelect;
private Scanner console;
public Student student;
public SetTest(){
coursesToSelect = new ArrayList<Course>();
console = new Scanner(System.in);
}
/**
* 用于往coursesToSelect中添加备选课程
*/
public void testAdd(){
//创建一个课程对象,并通过调用add方法,添加到备选课程List中
Course cr1 = new Course("1", "数据结构");
coursesToSelect.add(cr1);
Course temp1 = coursesToSelect.get(0);
Course cr2 = new Course("2", "C语言");
coursesToSelect.add(0, cr2);
Course temp2 = coursesToSelect.get(0);
Course[] course1 = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
coursesToSelect.addAll(Arrays.asList(course1));
Course temp3 = coursesToSelect.get(2);
Course temp4 = coursesToSelect.get(3);
Course[] course2 = {new Course("5", "高等数学"), new Course("6", "概率论与数理统计")};
coursesToSelect.addAll(2, Arrays.asList(course2));
Course temp5 = coursesToSelect.get(2);
Course temp6 = coursesToSelect.get(3);
}
/**
* 通过for each方法访问集合元素
*/
public void testForEach(){
System.out.println("有如下课程待选(通过for each访问):");
for(Course course:coursesToSelect){
System.out.println("课程:" + course.id + ":" + course.name);
}
}
/**
* 测试List的contains方法
*/
public void testListContains(){
//取得备选课程序列的第0个元素
Course course = coursesToSelect.get(0);
//打印输出coursesToSelect是否包含course对象
System.out.println("取得课程:" + course.name);
System.out.println("备选课程中是否包含课程:" + course.name + "," +
coursesToSelect.contains(course));
//提示输入课程名称
System.out.println("请输入课程名称:");
String name = console.next();
//创建一个新的课程对象,ID和名称,与course对象完全一样
Course course2 = new Course();
course2.name = name;
System.out.println("新创建课程:" + course2.name);
System.out.println("备选课程中是否包含课程:" + course2.name + "," +
coursesToSelect.contains(course2));
//通过indexOf方法来取得某元素的索引位置
if(coursesToSelect.contains(course2))
System.out.println("课程:" + course2.name + "的索引位置为:" +
coursesToSelect.indexOf(course2));
}
/**
* 测试List的containsAll方法
*/
public void testListContainsAll(){
/**
* 由于containsAll比较也需要经过equals方法
* 因此,重写equals方法时,只重写对比了name部分
* 因此在比较时,只需要比较name部分,id部分没有任何影响
*/
//创建一个集合,里面包含已存在的所有课程,id不同,name相同
Course[] course1 = {new Course("10000", "离散数学"), new Course("10", "汇编语言")};
System.out.println("备选课程中是否包含课程:" +
coursesToSelect.containsAll(Arrays.asList(course1)));
//创建一个集合,里面包含已存在的所有课程,id不同,name不同
Course[] course2 = {new Course("9", "离散数学"), new Course("10", "量子力学")};
System.out.println("备选课程中是否包含课程:" +
coursesToSelect.containsAll(Arrays.asList(course2)));
}
/**
*创建学生对象并选课
*/
public void createStudentAndSelectCours(){
//创建一个学生对象
student = new Student("1", "小明");
System.out.println("欢迎学生:" + student.name + "选课!");
//创建一个Scanner对象,用来接收从键盘输入的课程ID
Scanner console = new Scanner(System.in);
for(int i = 0;i < 3;i++) {
System.out.println("请输入课程ID");
String courseId = console.next();
for (Course cr : coursesToSelect) {
if (cr.id.equals(courseId)) {
student.courses.add(cr);
}
}
}
}
/**
* 测试Set的contains方法
*/
public void testSetContains(){
//提示输入课程名称
System.out.println("请输入学生已选的课程名称:");
String name = console.next();
//创建一个新的课程对象,ID和名称,与course对象完全一样
Course course2 = new Course();
course2.name = name;
System.out.println("新创建课程:" + course2.name);
System.out.println("备选课程中是否包含课程:" + course2.name + "," +
student.courses.contains(course2));
}
/**
* @param args
*/
public static void main(String[] args){
SetTest st = new SetTest();
st.testAdd();
st.testForEach();
st.testListContains();
st.testListContainsAll();
// st.createStudentAndSelectCours();
// st.testSetContains();
}
}
Student.java
package com.imooc.collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
/**
* 学生类
* @author Administrator
*/
public class Student implements Comparable<Student>{
public String id;
public String name;
//添加泛型
public Set<Course> courses;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public int compareTo(Student o) {
return this.id.compareTo(o.id);
}
public Student(String id, String name){
this.id = id;
this.name = name;
//利用HashSet实现类实例化courses
this.courses = new HashSet<Course>();
}
}
StudentComparator.java
package com.imooc.collection;
import java.util.Comparator;
public class StudentComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
TestGeneric.java
package com.imooc.collection;
import java.util.ArrayList;
import java.util.List;
public class TestGeneric {
/**
* 带有泛型——Course的List类型属性
*/
public List<Course> courses;
//在实例化时,ArrayList也需要添加泛型
public TestGeneric(){
this.courses = new ArrayList<Course>();
}
/**
* 测试添加
*/
public void testAdd(){
Course cr1 = new Course("1", "大学语文");
courses.add(cr1);
//泛型集合中,不能添加泛型规定的类型及其子类型以外的对象,否则会报错!
// courses.add("能否添加一些奇怪的东西呢?");
Course cr2 = new Course("2", "Java基础");
courses.add(cr2);
}
/**
* 测试遍历循环
*/
public void testForEach(){
for (Course cr:courses){
System.out.println(cr.id + ":" + cr.name);
}
}
/**
* 泛型集合可以添加泛型的子类型的对象实例
*/
public void testChild(){
ChildCourse ccr = new ChildCourse();
ccr.id = "3";
ccr.name = "我是子类型的课程对象实例";
courses.add(ccr);
}
/**
* 泛型不能使用基本类型
*/
public void testBasicType(){
//泛型不能使用基本类型,必须使用其包装类
// List list = new ArrayList();
List<Integer> list = new ArrayList<Integer>();
//自动装箱,将int类型1装箱成包装类Integer
list.add(1);
System.out.println("基本类型必须使用包装类作为泛型!" + list.get(0));
}
/**
* @param args
*/
public static void main(String[] args){
TestGeneric tg = new TestGeneric();
tg.testAdd();
tg.testForEach();
tg.testChild();
tg.testForEach();
tg.testBasicType();
}
}