目录
第十章 集合类
10.1 集合类概述
java.util 包中提供了一些集合类,这些集合类又被称为容器。提到容器不难想到数组,集合类与数组的不同之处是,数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型的数据,集合用来存放对象的引用。常用的集合有 List 集合、Set 集合和 Map 集合,其中 List 与 Set 继承了 Collection 接口,各接口还提供了不同的实现类。
10.2 Colleation接口
方法 | 功能描述 |
add(Object e) | 将指定的对象添加到该集合中 |
remove(Object) | 将指定的对象从该集合中移除 |
isEmoty() | 返回boolean值,用于判断当前集合是否为空 |
iterator() | 返回再此Collection的元素上进行迭代的迭代器。用于遍历集合中的对象 |
size() | 返回int型值,获取该集合中元素的个数 |
10.3 List集合
List 集合包括List接口以及List接口的所有实现类。List 集合中的元素允许重复,各元素的顺序就是对象插入的顺序。类似 Java 数组,用户可通过使用索引(元素在集合中的位置)来访问集合中的元素。
10.3.1 List接口
List 接口的常用实现类有 ArrayList 与 LinkedList。
方法 | 功能描述 |
get(int index) | 获取指定索引位置的元素 |
set(int index,Object obj) | 将集合中指定索引位置的对象修改为指定的对象 |
10.3.2 List接口的实现类
List<E> list=new ArrayList<>();
List<E> list2=new ArrayList<>();
在项目中创建ListTest类
package k10;
import java.util.*;
public class ListTest {
public static void main(String[] args) {//主方法
List<String> list=new ArrayList<>();//创建集合对象
list.add("a");//向集合添加元素
list.add("b");//向集合添加元素
list.add("c");//向集合添加元素
int i=(int) (Math.random()*list.size());//获取0~2之间的随机数
System.out.println("随机获取数组中的元素:"+list.get(i));
list.remove(2);
System.out.println("将索引是'2'的元素从数组移除后,数组中的元素是:");//将指定索引位置的元素从集合中移除
for(int j=0;j<list.size();j++) {//循环遍历数组
System.out.println(list.get(j));//获取指定索引处的值
}
}
}
运行结果
10.3.3 lterator迭代器
方法 | 功能描述 |
hasNext() | 如果仍有元素可以迭代,则返回trun |
next() | 返回迭代器的下一个元素 |
remove | 从迭代器指向的Collection中移除迭代器返回的最后一个元素(可选操作) |
在项目中创建IteratorTest类
package k10;
import java.util.*; //导入java.util包,其他实例都要添加该语句
public class IteratorTest { // 创建类useIterator
public static void main(String args[]) {
Collection<String> list = new ArrayList<>(); // 实例化集合类对象
list.add("a"); // 向集合添加数据
list.add("b");// 向集合添加数据
list.add("c");// 向集合添加数据
Iterator<String> it = list.iterator(); // 创建迭代器
while (it.hasNext()) { // 判断是否有下一个元素
String str = (String) it.next(); // 获取集合中元素
System.out.println(str);
}
}
}
运行结果
10.4 Set集合
Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合中,但 Set 集合中不能包含重复对象。Set 集合由 Set 接口和 Set 接口的实现类组成。
10.4.1 Set集合
Set 接口继承了 Collection 接口,因此包含 Collection 接口的所有方法。
10.4.2 Set接口的实现类
Set 接口常用的实现类有 HashSet 与 TreeSet。
HashSet 类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 Set 的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用 null 元素。该类实现了 Set 接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为 null 的元素,但最多只能一个。
TreeSet 类不仅实现了 Set 接口,还实现了 java.util.SortedSet 接口,因此,TreeSet 类实现的 Set 集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对用 TreeSet 类实现的 Set 集合中的对象进行排序。该类实现了Set接口,可以实现排序等功能。
方法 | 功能描述 |
first() | 返回此Set中当前第一个(最低)元素 |
last() | 返回此Set中当前最后一个(最高)元素 |
comparator() | 返回对此Set中的元素进行排序的比较器。如果此Set使用自然顺序,则返回null |
headSet(E toElement) | 返回一个新的Set集合,新集合是toElement(不包含)之前的所以对象 |
subSet(E fromElement,E toElement) | 返回一个新的Set集合,是fromElent(包含)对象与toElement(不包含)对象之间的所有对象 |
tailSet(E fromElement) | 返回一个新的Set集合,新集合包含对象fromElement(包含)之后的所有对象 |
10.4.3 TreeSet的两种排序方式
1.引用排序
package ketanglianxi;
import java.util.*;
public class test1 {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();
treeSet.add(10);
treeSet.add(11);
treeSet.add(13);
treeSet.add(12);
for (Object object : treeSet) {
System.out.print(object + " " );
}
}}
运行结果
package ketanglianxi;
import java.util.*;
public class Book{
public static void main(String[] args) {
private Integer bookId;
private String bookName;
private String bookAuthor;
private Double price;
}
/*
测试类
*/
public void test2() {
Book book1 = new Book(1, "红楼梦", "曹雪芹",11.0);
Book book2 = new Book(2, "西游记", "曹雪芹",13.0);
Book book3 = new Book(3, "水浒传", "曹雪芹",12.0);
TreeSet treeSet = new TreeSet();
treeSet.add(book1);
treeSet.add(book2);
treeSet.add(book3);
for (Object object : treeSet) {
Book book = (Book)object;
System.out.println(book.getBookName() + book.getPrice());
}
}
}
运行结果
2.自定义类型排序
如果集合存储的是自定义类型,当存入自定义的引用类型的时候就必须考虑到元素要求具有可排序性,不然会引发ClassCastException异常,所以要对自定义类型进行处理,必须要实现 Comparable或Compared接口。当把一个对象加入TreeSet集合中时,TreeSet调用该对象的compareTo(Object obj)方法与容器中的其他对象比较大小,然后根据红黑树算法决定它的存储位置。
2.1 自然排序
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系,然后将集合元素按升序排列,这种方式就是自然排序。(比较的前提:两个对象的类型相同)。
操作步骤:
1、Book类实现Comparable接口;
2、重写Comparable接口中的compareTo方法。
package ketanglianxi;
import java.util.*;
public class Book{
public static void main(String[] args) {
/*
实体类:Book
*/
public class Book {
private Integer bookId;
private String bookName;
private String bookAuthor;
private Double price;
}
/**
测试类
*/
public void test4() {
Book book1 = new Book(1, "红楼梦", "曹雪芹",11.0);
Book book2 = new Book(1, "西游记", "曹雪芹",3.0);
Book book3 = new Book(1, "水浒传", "曹雪芹",12.0);
/**
compare有两个参数,o1和o2,如果
o1 < o2 返回负数,
o1 = o2 返回正数,
o1 > o2 返回正数。
*/
TreeSet treeSet = new TreeSet(new Comparator() { // 匿名内部类操作
public int compare(Object o1, Object o2) {
Book book1 = (Book)o1;
Book book2 = (Book)o2;
return (int)( book1.getPrice() - book2.getPrice());
}
});
treeSet.add(book1);
treeSet.add(book2);
treeSet.add(book3);
for (Object object : treeSet) {
Book book = (Book)object;
System.out.println(book.getBookName() + book.getPrice());
}
}}
运行结果
2.2 定制排序
TreeSet的自然排序是根据集合元素的大小,TreeSet将他们以升序排列。如果需要实现定制排序,例如降序,则可以使用Comparator接口。该接口里包含一个int compare(T o1, T o2)方法,该方法用于比较o1和o2的大小。如果需要实现定制排序,则需要在创建TreeSet集合对象时,并提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。
操作步骤:
让集合构造方法接收Comparator的实现类的compare()方法。
package ketanglianxi;
import java.util.*;
public class Book{
public static void main(String[] args) {
/*
实体类:Book
*/
public class Book {
private Integer bookId;
private String bookName;
private String bookAuthor;
private Double price;
}
/**
测试类
*/
public void test4() {
Book book1 = new Book(1, "红楼梦", "曹雪芹",11.0);
Book book2 = new Book(1, "西游记", "曹雪芹",3.0);
Book book3 = new Book(1, "水浒传", "曹雪芹",12.0);
/**
compare有两个参数,o1和o2,如果
o1 < o2 返回负数,
o1 = o2 返回正数,
o1 > o2 返回正数。
*/
TreeSet treeSet = new TreeSet(new Comparator() { // 匿名内部类操作
public int compare(Object o1, Object o2) {
Book book1 = (Book)o1;
Book book2 = (Book)o2;
return (int)( book1.getPrice() - book2.getPrice());
}
});
treeSet.add(book1);
treeSet.add(book2);
treeSet.add(book3);
for (Object object : treeSet) {
Book book = (Book)object;
System.out.println(book.getBookName() + book.getPrice());
}
}}
运行结果
10.5 Map集合
Map 集合没有继承 Collection 接口,其提供的是 key 到 value 的映射。Map 中不能包含相同的 key,每个 key 只能映射一个 value。key 还决定了存储对象在映射中的存储位置,但不是由 key 对象本身决定的,而是通过一种“散列技术”进行处理,产生一个散列码的整数值。散列码通常用作一个偏移量,该偏移量对应分配给映射的内存区域的起始位置,从而确定存储对象在映射中的存储位置。Map 集合包括Map 接口以及 Map 接口的所有实现类。
10.5.1 Map接口
Map接口提供了将Key映射到值的对象。
10.5.2 Map接口的实现类
Map 接口常用的实现类有 HashMap 和 TreeMap。
HashMap 类是基于哈希表的 Map 接口的实现,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键,但必须保证键的唯一性。HashMap 通过哈希表对其内部的映射关系进行快速查找。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。HashMap 继承于 AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
TreeMap 类不仅实现了 Map 接口,还实现了 java.util.SortedMap 接口,因此,集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系时,TreeMap 类比 HashMap 类性能稍差。由于 TreeMap 类实现的 Map 集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是 null。
package k10;
import java.util.*;
public class HashMapTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>(); // 创建Map实例
map.put("ISBN-978654", "Java从入门到精通"); // 向集合中添加对象
map.put("ISBN-978361", "Android从入门到精通");
map.put("ISBN-978893", "21天学Android");
map.put("ISBN-978756", "21天学Java");
Set<String> set = map.keySet(); // 构建Map集合中所有key对象的集合
Iterator<String> it = set.iterator(); // 创建集合迭代器
System.out.println("key值:");
while (it.hasNext()) { // 遍历集合
System.out.print(it.next()+"\t");
}
Collection<String> coll = map.values(); // 构建Map集合中所有values值集合
it = coll.iterator();
System.out.println("\nvalues值:");
while (it.hasNext()) { // 遍历集合
System.out.print(it.next()+"\t");
}
}
}
运行结果
10.6 集合的使用场合
List集合、Set集合和Map集合,那么在实际开发中,应该选用合适的集合。
List 集合关注的是索引,其元素是顺序存放的,例到如一个班的学生成绩,成绩可以重复就可以使用List集合存取。
Set集合关注唯一性,它的值不允许重复,例如每个班的学生的学号,每个学生的学号是不能重复的。
Map集合关注的是唯一的标识符(KEY),它将唯一的键映射到某个元素,例如每个班学生的学号与姓名的映射,每个学号对应一个学生的姓名,学号是不能重复的,但是学生的姓名有可能重复。
10.7 小结
本章节介绍了父接口Collection,List集合,Set集合和Map集合。重点掌握遍历集合,添加对象,删除对象方法。