You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
8.7 KiB
Markdown

2 years ago
Set集合与Map是用得非常多的有别于有序容器的另外一类容器。集合的概念与数学中的集合概念一致多值且不重复这个需要和List等容器进行区别List等前面学习的容易可以在一个容器中包含多个相同的值但是Set集合却不行。Map是一种特殊的容器或者被称为Key-Value容器一个记录包含两个值其中Key是索引有点像数据库中的表。
## 1. Collection的Set接口
回顾一下上一张的collection类属关系Collection接口的子接口有三个Queue、List、Set前两个已经讲过了这里我们看看Set接口。
![Alt text](img/image-20230331084818875.png)
> The Set interface extends the Collection interface. It does not introduce new methods or constants, but it stipulates that an instance of Set contains no duplicate elements. The concrete classes that implement Set must ensure that no duplicate elements can be added to the set. That is no two elements e1 and e2 can be in the set such that e1.equals(e2) is true.
>
> Set 接口由Collection接口扩展而来并没有引入新的方法和常量只是规定Set中不会保存重复的元素。实现Set接口的类必须保证不出现两个相同的对象即不能出现 `e1.equals(e2)`为真的情况。
总之一句话Set中的元素必须是唯一的。
![image-20230402182923594](img/image-20230402182923594.png)
从上图中可以看到类和接口的关系上图不用去记住只需要知道HashSet实现了Set接口就可以了。Set还有其他的实现例如LinkedHashSetTreeSet等。这里我们只需要掌握HashSet的使用。
```java
import java.util.*;
public class TestHashSet {
public static void main(String[] args) {
// Create a hash set
Set<String> set = new HashSet<String>(); // 变量是Set类型实际对象是HashSet
// Add strings to the set
set.add("London");
set.add("Paris");
set.add("New York");
set.add("San Francisco");
set.add("Beijing");
set.add("New York");
System.out.println(set);
// Display the elements in the hash set
for (String s : set) {
System.out.print(s.toUpperCase() + ":");
}
}
}
```
可以看到`New York`虽然被添加了两次但set中只存在一个。如果使用`set.size()`得到set的大小值是5实际添加了6次一次重复的被忽略
当然,如果写成:
```java
AbstractSet<String> set = new HashSet<String>();
HashSet set = new HashSet<String>();
Collection<String> set = new HashSet<String>();
```
也是可以了,引用变量只是能力申明。
另外需要注意Set是无序的没有index的概念不能使用下标来引用其中的元素因此无法使用传统的for循环只能使用如上述的增强for循环。
到现在我们发现同一种类型的容器例如List、Queue、Set这些接口都有很多不同的实现例如HashSetTreeSet其实这些不同的实现都是为了考虑不同的应用场景多线程安全性读取或者写入优化是否排序等等。因此不同的应用场景选择不同的实现是很有必要的否则会降低程序的运行效率甚至会出错。
### 1.1. 统计关键词总数量
```java
import java.util.*;
import java.io.*;
public class CountKeywords {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(System.in);
System.out.print("Enter a Java source file: ");
String filename = input.nextLine();
File file = new File(filename);
if (file.exists()) {
System.out.println("The number of keywords in " + filename + " is " + countKeywords(file));
} else {
System.out.println("File " + filename + " does not exist");
}
}
public static int countKeywords(File file) throws Exception {
// Array of all Java keywords + true, false and null
String[] keywordString = { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class",
"const", "continue", "default", "do", "double", "else", "enum", "extends", "for", "final", "finally",
"float", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native",
"new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super",
"switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while",
"true", "false", "null" };
Set<String> keywordSet = new HashSet<String>(Arrays.asList(keywordString));
int count = 0;
Scanner input = new Scanner(file);
while (input.hasNext()) {
String word = input.next();
if (keywordSet.contains(word))
count++;
}
return count;
}
}
```
上面这个例子作为了解,可以分析一下这个程序到底要做什么?
## 2. Map接口
> The Map interface maps keys to the elements. The keys are like indexes. In List, the indexes are integer. In Map, the keys can be any objects.
>
2 years ago
> Map 接口中每个元素都是一个key-value的映射。Key如同是索引在数组中索引是整形integer在Map中Key可以是任何的引用类型Object及其子对象
>
2 years ago
>
![image-20230402203448937](img/image-20230402203448937.png)
> An instance of Map represents a group of objects, each of which is associated with a key. You can get the object from a map using a key, and you have to use a key to put the object into the map.
2 years ago
>
> 每一个Map的实例都代表一系列的对象组每组中有个Key。你可以通过Key值获取一个Value当添加的时候必须使用key-value的形式。
2 years ago
![image-20230402203548339](img/image-20230402203548339.png)
引用网上一个比较完整的类图:[容器框架概述](https://blog.csdn.net/WZD2012/article/details/73245493)
2 years ago
![map](img/map.jpeg)
2 years ago
2 years ago
下图是Map接口的基本定义通过函数名可以知道其基本的含义。
2 years ago
2 years ago
![image-20230402203619454](img/image-20230402203619454.png)
2 years ago
2 years ago
下图是Map接口的其他实现包括HashMapLinkedHashMapTreeMap。每个Map的具体实现的引用场景不太一样大家只需要掌握HashMap和Map接口的基本使用就可以了。
2 years ago
![image-20230402203630858](img/image-20230402203630858.png)
![image-20230402203649477](img/image-20230402203649477.png)
### 2.1. HashMap
```java
import java.util.*;
public class TestMap {
public static void main(String[] args) {
// Create a HashMap
Map<String, Integer> hashMap = new HashMap<String, Integer>();
hashMap.put("Smith", 30);
hashMap.put("Anderson", 31);
hashMap.put("Lewis", 29);
hashMap.put("Cook", 29);
2 years ago
hashMap.put("Cook", 31); // 修改 Cooke 的值为 31以前Cooke为29的被改写了
2 years ago
System.out.println("Display entries in HashMap");
System.out.println(hashMap + "\n");
// Create a TreeMap from the preceding HashMap
Map<String, Integer> treeMap = new TreeMap<String, Integer>(hashMap);
System.out.println("Display entries in ascending order of key");
System.out.println(treeMap);
// Create a LinkedHashMap
Map<String, Integer> linkedHashMap = new LinkedHashMap<String, Integer>(16, 0.75f, true);
linkedHashMap.put("Smith", 30);
linkedHashMap.put("Anderson", 31);
linkedHashMap.put("Lewis", 29);
linkedHashMap.put("Cook", 29);
// Display the age for Lewis
System.out.println("\nThe age for " + "Lewis is " + linkedHashMap.get("Lewis"));
System.out.println("Display entries in LinkedHashMap");
System.out.println(linkedHashMap);
}
}
```
2 years ago
输入结果是:
```java
Display entries in HashMap
{Lewis=29, Smith=30, Cook=31, Anderson=31}
Display entries in ascending order of key
{Anderson=31, Cook=31, Lewis=29, Smith=30}
The age for Lewis is 29
Display entries in LinkedHashMap
{Smith=30, Anderson=31, Cook=29, Lewis=29}
```
这里一共3个Map的实现HashMap、TreeMap和LinkedHashMap基本使用都一样。
`HashMap<String, Integer>()`
2 years ago
2 years ago
Map的put方法是向Map中增加一个Key-Value的值第一个参数是Key第二个参数是Value。
2 years ago
### 2.2. 统计单词出现次数
```java
import java.util.*;
public class CountOccurrenceOfWords {
public static void main(String[] args) {
String text = "Good morning. Have a good class. Afternoon. Have a good time. " + "Have a good visit. Have fun!";
Map<String, Integer> map = new TreeMap<String, Integer>();
String[] words = text.split("[ \n\t\r.,;:!?(){}]");
for (int i = 0; i < words.length; i++) {
String key = words[i].toLowerCase();
if (key.length() > 0) {
if (!map.containsKey(key)) {
map.put(key, 1);
} else {
int value = map.get(key);
value++;
map.put(key, value);
}
}
}
for (String i : map.keySet()) {
int v = map.get(i);
System.out.printf("%s\t%d\n", i, v);
}
}
}
```
## 3. 本章重点
1. 掌握Set的概念和接口基本使用
2. 结合HashMap类掌握Map的概念和基本使用。