Week2 Using the Java Collection Libraries Lecture 2

1. Java为数据结构编程提供了哪些支持?

(1)Java 提供了丰富的数据结构类 ,通过 Java 集合框架(Java Collections Framework) 来实现,常见的包括:

Java 集合框架(Java Collections Framework,简称 JCF) 是一组 用于存储和操作数据 的类和接口的集合,提供了一种统一的方式来管理、存取和操作不同类型的数据结构。它为开发者提供了各种现成的、可复用的数据结构类

列表(List):用于存储有序元素集合,如 ArrayList、LinkedList。

集合(Set):用于存储不重复的元素,如 HashSet、TreeSet。

队列(Queue):用于按先进先出(FIFO)顺序处理元素,如 LinkedList、PriorityQueue。

映射(Map):用于存储键值对,如 HashMap、TreeMap。

栈(Stack):处理元素时采用先进后出(LIFO)方式,如 Stack 类。

(2)Java 还提供了泛型支持,允许用户为数据结构中的元素定义类型,这提高了类型安全性和复用性。

2. 使用 Java 可以创建哪些类型的数据结构?

数组(Array):固定大小的结构,用于存储相同类型的元素。

列表(List):如 ArrayList、LinkedList,提供动态数组和链表。

栈(Stack):可以使用 Stack 或 Deque 实现 LIFO 功能。

队列(Queue):使用 Queue、LinkedList 或 PriorityQueue 实现 FIFO 功能。

集合(Set):如 HashSet、TreeSet,用于存储唯一元素。

映射(Map):如 HashMap、TreeMap,用于存储键值对。

树(Tree):可以通过自定义代码或使用内置类如 TreeMap、TreeSet 来实现。

图(Graph):可以使用 Map 来表示邻接列表,或者自己实现。

堆(Heap):常使用优先队列实现堆数据结构。

3. 如何在 Java 中创建和访问数据结构?

在 Java 中,数据结构可以通过以下方式创建和访问:

(1) 创建数据结构:

• 示例:创建一个整数列表:

List<Integer> myList = new ArrayList<>();

• 示例:创建一个 HashMap:

Map<String, Integer> myMap = new HashMap<>();

(2)访问数据结构:

ArrayList(列表):

myList.add(10); // 添加元素
Integer value = myList.get(0); // 访问索引为 0 的元素

HashMap(映射):

myMap.put("key1", 100); // 添加键值对
Integer value = myMap.get("key1"); // 通过键访问值

Java 的 集合框架 提供了直观且高效的方法来访问、添加和修改数据结构。

4. 一些实际例子?

以下是 Java 数据结构的一些实际应用示例:

(1) 待办事项应用:可以使用 ArrayList 存储任务,动态地添加、删除和管理任务。

(2) 缓存系统:可以使用 HashMap 实现内存缓存,将数据存储为键值对。

(3) 优先级调度:可以使用 PriorityQueue 实现优先级调度系统,根据优先级处理任务。

(4) 图遍历:可以使用 Map 或 Set 来表示图,适用于社交网络应用,节点(人)通过边(友谊)连接。

(5) 排队模拟:可以使用 Queue 模拟客户服务或交通管理等场景,按 FIFO 顺序处理请求。

**一、**Overview of Data Structure Programming

1. 线性集合编程(Programming with Linear collections)

(1) 线性集合的种类

• 列表(Lists)、集合(Sets)、袋(Bags)、映射(Maps)、栈(Stacks)、队列(Queues)、优先队列(Priority Queues)。

(2) 使用线性集合

• 集合编程(Programming with collections)

• 数据的搜索与排序(Searching & Sorting Data)

• 实现线性集合(Implementing linear collections)

• 实现排序算法(Implementing sorting algorithms)

• 链式数据结构和"指针"概念(Linked data structures and "pointers")

2. 分层集合编程(Programming with Hierarchical collections)

(1) 分层集合的种类

• 树(Trees)、二叉树(Binary trees)、通用树(General trees)。

(2)使用树结构集合structured collections

• 构建树结构(Building tree structures)

• 搜索树结构(Searching tree structures)

• 遍历树结构(Traversing tree structures)

(3) 实现树结构集合

(4) 实现线性集合:使用二叉搜索树(with binary search trees)

二、编程与库(Programming with Libraries)

  1. 现代程序(尤其是 GUI 和网络)太复杂,不能从头开始编写

必须重用他人编写的代码。

  1. 库是为重用而设计的代码集合

Java有大量的标准库,例如 java.util、java.io 等,提供了各种实用的类和工具。

库是由包(Packages)和类(Classes)组成的。一个包可以包含多个相关的类,简化代码的组织和使用。

包(Package) 是类和其他类型(如接口、子包)的集合

• 类实现接口。一个类可以实现一个或多个接口,但它必须提供接口中声明的所有方法的具体实现。

(1)Libraries

java.util:集合类和其他实用类。

Collection classes and other utilityclasses.

java.io:输入输出类。

javax.swing 和 java.awt:用于 GUI 程序的大型类库。

我们将在几乎所有程序中使用这些库。

java.util 是一个,它包含了像 ArrayList、HashSet、LinkedList 等类。

(2)使用库(Using Libraries)

使用库时,阅读文档以选择有用的库。

• 使用 import 语句导入必要的包/类,如

import java.util.*

import java.io.*

• 注意文档中描述的构造函数、方法和接口。

• 像使用程序中自有的类一样使用这些类。

• 构造函数(Constructors)用于创建实例(making instances)

• 方法(Methods)用于调用

• 接口(Interfaces)用于实现

三、Collections

1. 标准集合("Standard" Collections)

• 常见的集合类型:

袋(Bag)、集合(Set)、映射(Map)、列表(List)、队列(Queue)、栈(Stack)、树(Tree)、图(Graph)。

Bag:一个无序的集合,可能包含重复元素。

Set:一个无序的集合,不允许重复元素。

Map:一个存储键值对的集合。

List:一个有序集合,可以通过索引位置访问元素。

Queue:一个有限访问的集合,通常遵循 FIFO(先进先出)原则。

Stack:一个遵循 LIFO(后进先出)原则的集合。

Tree:一种层次化的集合,常用于存储有序数据。

Graph:一个由节点和边组成的集合,用来表示对象之间的关系。

• 这些类型在数据结构化组织方式 、以及如何处理重复和访问方面有所不同。

• 元素的具体类型 及其存储 /操作方式是抽象化的。

2. Abstract Data Types

抽象数据类型(ADT) 是一种数据类型,它描述了数据结构的 操作行为 ,但并不涉及数据是如何实现的。简而言之,ADT 强调了 操作接口行为规范,而不关心其内部的实现细节。

• ADT 用来定义一类数据对象的集合,并指定允许对该数据进行的操作

Set, Bag, Queue, List, Stack, Map, etc are Abstract Data Types (outcome of abstraction / encapsulation)

• 例如,Set ADT:

操作包括 add(value)、remove(value) 和 contains(value)。

• 新集合的初始状态:一个新的 Set 不包含任何元素。

• 元素添加与移除的条件:

集合 包含 某个值 当且仅当:该值已被添加并且没有被移除。

集合 不包含 某个值 当且仅当:该值从未被添加,或已被移除并且没有再添加回来。

行为指定了每个操作的预期结果,但没有涉及实现细节。

3. Java Collections library

Java 集合库定义了几个重要的接口:

Collection:所有集合的最通用接口。

List:表示有序集合(如 ArrayList、LinkedList)。

Set:表示无序且没有重复元素的集合(如 HashSet、TreeSet)。

Queue:表示有序集合,且有限制访问的集合(如 LinkedList)。

Map:表示键值对的集合(如 HashMap、TreeMap)。

Collection 接口 作为 Java 中最通用的集合接口,类似于Bag。也就是说,Collection 接口的设计考虑了最一般的集合特性,适用于各种类型的集合(如 List、Set、Queue),其功能可以扩展到包含不同的集合类型和不同的操作。

Bag 表示一个无序的集合,允许重复元素

• 每个实现这些接口的(例如 ArrayList、LinkedList、HashSet、HashMap)提供不同的内部实现,但都遵循接口指定的规则。

4. Java Interfaces and ADT's

(1) 接口与 ADT 的关系:

Java 接口 对应于 抽象数据类型(ADT)。

抽象数据类型(ADT) 是在抽象层面上定义的数据类型,指定了可以对该类型的对象执行的 操作,以及该对象应该如何 表现。

Java 接口 指定了可以在特定类型的对象上调用的方法。它定义了方法的签名,包括:

• 方法的 名称。

• 方法的 参数(及其类型)。

• 方法的 返回类型。

行为 只在注释中给出,但在接口中并不能强制执行。举例来说,接口中的方法列出的是方法的签名,而没有方法的具体实现。

(2) Java 接口的主要特点:

没有构造函数:No constructors

接口不能被直接实例化:new Set()

没有字段:No fields

接口不能定义字段(即实例变量)。接口不指定数据是如何存储的。

没有方法体:No method bodies.

• 接口只定义了 方法签名,没有方法的具体实现。方法体(即方法的具体实现)留给实现该接口的类来完成。

(3) Set 接口示例

public interface Set {

public void add(??? item); // 添加元素

public void remove(??? item); // 移除元素

public boolean contains(??? item); // 检查元素是否存在

}

四、Programming with Lists of Objects

1. List Interface in Java

• Java中的List接口扩展了 Collection<E>,其中 <E> 代表列表中元素的类型。

包含的方法有:

• add(E o) 用于添加元素。

• get(int index) 用于通过索引访问元素。

• contains(Object o) 用于检查某个元素是否存在于列表中。

• iterator() 用于遍历元素。

• List 接口允许有序集合,并通过索引进行访问。

以下是每张图片中涉及的知识点的详细阐述和总结:

2. Using Java Collection Interfaces(使用 Java 集合接口)

(1) 声明接口的变量、参数或字段:

• 在 Java 中,我们可以声明一个变量、参数或字段,使用集合接口类型来定义集合的类型。比如:

private List drawing; // a list of Shapes

• 这段代码声明了一个名为 drawing 的变量,它是 List 类型的,可以存储 Shape 类型的元素(例如不同的形状 Rectangle、Circle 等)。这里的List 是一个接口,意味着 drawing 可以使用任何实现了 List 接口的类(例如 ArrayList 或 LinkedList)。

(2) 调用方法:

• 你可以通过该变量调用集合接口中定义的方法。例如:

drawing.add(new Rect(100, 100, 20, 30));

• 这行代码向 drawing 列表中添加一个新的 Rect 对象,Rect 是 Shape 类型的一个子类。调用 add() 方法将新的元素添加到列表中。

(3)问题:如何指定集合中元素的类型?

• 这其实是关于 泛型 的问题,集合接口本身并不指定集合元素的具体类型。我们可以通过泛型在声明时指定集合中元素的类型,例如 List<Shape> 表示一个只能存储 Shape 类型对象的列表。

3. Parameterized Types(参数化类型)

(1) 集合类型的结构和访问规则相同:

• 无论集合存储什么类型的元素(如 String、Person、Shape 或整数),集合的结构和访问规则(access discipline)是相同的。

• 例如,Set<String> 和 Set<Integer> 都是集合类型,它们都遵循相同的访问和操作规则,只不过存储的元素类型不同。

(2) 只需要一个接口来表示每种集合类型:

• 对于不同类型的集合,只需要一个集合接口(如 Set)即可。例如:

• 一个 Set 接口可以用来表示存储任何类型的元素的集合,具体元素类型是在使用该接口时指定的。

• Set<String> 是一个存储字符串的集合,而 Set<Person> 是一个存储 Person 对象的集合。

(3) 集合接口和类是参数化的 ,即可以通过泛型来指定集合的类型和集合中元素的类型。

4. Parameterized Types: Interfaces with Type Parameters(参数化类型:带类型参数的接口)

(1) 接口带类型参数:

• 接口可以有类型参数,如 Set<T>。T 是类型参数,表示集合中存储的元素类型。它没有具体指定元素的类型,可以在使用该接口时根据需要传递具体类型(如 Set<String> 或 Set<Person>)。

public interface Set<T> {

public void add(T item);

public void remove(T item);

public boolean contains(T item);

}

• 这样,T 表示一个占位符,具体的类型将在使用时指定。

List<T>、Set<T> 这些集合接口都使用类型参数 T 来表示集合中元素的类型。

(2)声明变量时指定集合元素的类型:

• 当声明一个集合变量时,我们不仅指定集合的类型(如 Set 或 List),还要指定集合元素的类型。例如:

private Set<Person> friends;

private List<Shape> drawing;

• 这里,friends 变量是一个 Set 类型的集合,它只存储 Person 类型的对象,而 drawing 变量是一个 List 类型的集合,它只存储 Shape 类型的对象。

5. Using the Java Collection Library(使用 Java 集合库)

(1) 接口不能直接实例化:

• 接口不能直接实例化,因为接口只是定义了方法的签名,并没有实现这些方法。例如,不能这样创建:

List<Shape> drawing = new List<Shape>(); // 错误,List 是接口,不能实例化

(2) 类实现接口并提供具体实现:

• Java 中的集合类(如 ArrayList、HashSet 等)实现了集合接口,提供了实际的功能实现。这些类提供了构造函数来创建实例定义了方法体来执行集合操作。例如:

private List<Shape> drawing = new ArrayList<Shape>();

Set<Person> friends = new HashSet<Person>();

6. ArrayList

(1)ArrayList 是 Java 集合框架的一部分:

• ArrayList 是 Java 集合框架中的一个类,用于存储有序的元素。与传统数组不同,ArrayList 可以动态扩展大小。

• 使用 ArrayList 时,必须导入 java.util 包:part of the java.util package

import java.util.*;

(2)可以创建新的 ArrayList 对象:

• 当你创建一个新的 ArrayList 对象时,你不需要事先指定它的大小。你只需要指定集合元素的类型。例如:

private ArrayList<Shape> drawing = new ArrayList<Shape>();

• 这种方式类似于一个动态数组,不需要设置固定的大小,可以根据需要扩展。

infinitely stretchable array

  1. 你不能使用 [] 角括号的数组访问方式(不像普通数组 array[i] 这样访问元素)。

示例(错误的写法):

ArrayList<Integer> numbers = new ArrayList<>();

numbers.add(10);

System.out.println(numbers[0]); // ❌ 错误!ArrayList 不能用 []

必须使用 ArrayList 的方法来访问和修改元素,而不能直接用 []。

主要用的方法:

• add(value): 添加元素

• get(index): 获取元素

• set(index, value): 修改元素
int firstNumber = numbers.get(0); // ✅ 使用 get() 访问

System.out.println(firstNumber); // 输出: 10

7. Using ArrayList: Declaring

(1)声明数组和 ArrayList:

• 当使用传统数组时,必须指定数组的大小:

private static final int maxStudents = 1000;

private Student[] students = new Student[maxStudents];

private int count = 0;

• 这种方式需要事先知道数组的大小,而 ArrayList 则无需指定大小,且没有最大限制。

(2) **使用 ArrayList 代替数组:**No maximum; no initial size; no explicit count

• 使用 ArrayList 时,数组的固定大小不再是问题,且可以灵活地增加元素。例如:

private ArrayList<Student> students = new ArrayList<Student>();

普通数组(Array)中,必须手动维护一个 count 变量来跟踪当前存储的元素数量。例如:

private static final int maxStudents = 1000;

private Student[] students = new Student[maxStudents];

private int count = 0; // 👈 手动维护当前存储的学生数量

public void addStudent(Student s) {

if (count < maxStudents) {

students[count] = s;

count++; // 👈 需要手动更新 count

}

}

8. Using ArrayList: Methods

Java ArrayList 的常用方法

1️⃣ size() :返回 ArrayList 中的元素个数。

2️⃣ add(item):向列表末尾添加元素。

3️⃣ add(index, item):在指定索引 index 处插入 item,后续元素右移。

4️⃣ set(index, item):替换指定索引 index 处的元素。

5️⃣ contains(item):检查列表是否包含某个元素,返回 true 或 false。

6️⃣ get(index):获取指定索引 index 处的元素。

7️⃣ remove(item):删除 ArrayList 中第一个匹配 item 的元素。

8️⃣ remove(index):删除 index 位置的元素,后续元素左移。

示例

ArrayList<String> list = new ArrayList<>();
list.add ("Alice");

list.add("Bob");

System.out.println(list.size()); // 输出: 2

list.add (1, "David");

System.out.println(list); // 输出: [Alice, David, Bob]

list.set (2, "Eve");

System.out.println(list); // 输出: [Alice, David, Eve]

System.out.println(list.contains("Alice")); // 输出: true

System.out.println(list.get(1)); // 输出: David

list.remove ("David");

System.out.println(list); // 输出: [Alice, Eve]

list.remove (1);

System.out.println(list); // 输出: [Alice]

9️⃣ 遍历 ArrayList两种方式

  1. for 循环:

for (int i = 0; i < list.size(); i++) {

System.out.println(list.get(i));

}

  1. for-each 循环:

for (String name : list) {

System.out.println(name);

}

9. Using ArrayList (代码示例)

主要知识点:如何使用 ArrayList 存储 Student 对象

1️⃣ ArrayList<Student> 的声明

创建 ArrayList 来存储 Student 类型对象

private ArrayList<Student> students = new ArrayList<Student>();

2️⃣ 添加学生对象

两种方式:

Student s = new Student("Lindsay King", "300012345");
students.add(s);  // 直接添加对象

students.add(0, new Student(fscanner)); // 在索引 0 位置插入

3️⃣ 遍历 ArrayList<Student>

如果类没有重写 toString() 方法,System.out.println(obj) 只会打印对象的哈希码,而不是我们想要的内容。因此,我们需要 toString() 方法来定义对象的可读格式

for 循环

for (int i = 0; i < students.size(); i++) {
    System.out.println(students.get(i).toString());
}

增强 for-each 循环

for (Student st : students) {
    System.out.println(st.toString());
}

4️⃣ 检查是否包含某个对象

使用 contains() 判断是否有某个学生

if (students.contains(current)) {
    file.println(current);
    students.remove(current);
}

五、Q&A

1️⃣ Java 线性集合(Linear Collections)

• ArrayList

• LinkedList

• Vector(和 ArrayList 一样,Vector 也可以动态扩容)

2️⃣ 线性集合的常见操作

• 添加元素 (add())

• 访问元素 (get())

• 修改元素 (set())

• 删除元素 (remove())

3️⃣ Java 层次集合(Hierarchical Collections)

• TreeSet

• HashMap

4️⃣ 层次集合的常见操作

• 插入 (put())

• 查找 (get())

• 删除 (remove())

• 检查存在性 (containsKey() 或 containsValue())

5️⃣ 什么是软件库(Software Library)?

一组预定义的类和方法,提供通用功能(如 Java Standard Library)。

6️⃣ Java Package 是什么?

• 组织类的方式,类似于文件夹,避免类名冲突。

package myPackage;

7️⃣ Java 的 IO 库

java.io

java.nio

8️⃣ Java 的 GUI 库

javax.swing

java.awt

9️⃣ 导入 Java 包的语句

• 使用 import 关键字

import java.util.ArrayList;

六、Conclusions(总结)

1️⃣ 我们可以声明一个变量/字段/参数的类型为某个元素类型的集合

示例

List<String> names = new ArrayList<>();

2️⃣ 可以创建合适的集合类

示例

Set<Integer> numbers = new HashSet<>();

3️⃣ 如何选择合适的集合类?

• ArrayList 适合随机访问

• LinkedList 适合频繁插入/删除

• HashSet 适合去重存储

• HashMap 适合键值对存储

相关推荐
小萌新上大分几秒前
easyExcel使用案例有代码
java·java-ee·easyexcel·easyexcel使用·web文件导出·easyexcel入门教程
L_cl16 分钟前
【Python 数据结构 3.顺序表】
数据结构
深鱼~19 分钟前
【数据结构】LRUCache|并查集
数据结构
Y雨何时停T1 小时前
Java 容器之 List
java·开发语言·list
信徒_1 小时前
Netty介绍
java
m0_672656541 小时前
如何把图片或者图片地址存到 MySQL 数据库中以及如何将这些图片数据通过 JSP 显示在网页中
java·数据库·mysql
大丈夫在世当日食一鲲1 小时前
Java的流表达式使用
java·开发语言·windows
多多*1 小时前
题解 | 牛客周赛83 Java ABCDEF
java·开发语言·macos·objective-c·cocoa·工厂方法模式
熊出没1 小时前
解锁责任链模式:Java 实战与应用探秘
java·开发语言·责任链模式
码熔burning1 小时前
(十 六)趣学设计模式 之 责任链模式!
java·设计模式·责任链模式