一、集合
Java集合类存放在java.util包中,是一个用来存放对象的容器。
- 集合只能存放对象,基本数据类型会自动转换成对应的引用类型。
- 集合存放的都是对象的引用,而非对象本身,对象本身还是放在堆内存中。
- 集合可以存放不同类型,不限数量的数据类型。
集合框架如下:
(一)、Collection接口
1、List接口
(1)LinkedList(链表)
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表分类:
- 单向链表
- 双向链表
LinkedList的使用场景:
- 需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
LinkedList实现的接口:
- LinkedList 继承了 AbstractSequentialList 类。
- LinkedList 实现了 Queue 接口,可作为队列使用。
- LinkedList 实现了 List 接口,可进行列表的相关操作。
- LinkedList 实现了 Deque 接口,可作为队列使用。
- LinkedList 实现了 Cloneable 接口,可实现克隆。
- LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。
常用方法:
方法 | 描述 |
---|---|
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public void add(int index, E element) | 向指定位置插入元素。 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 |
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 |
public void clear() | 清空链表。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 |
public E remove(int index) | 删除指定位置的元素。 |
public E poll() | 删除并返回第一个元素。 |
public E remove() | 删除并返回第一个元素。 |
public boolean contains(Object o) | 判断是否含有某一元素。 |
public E get(int index) | 返回指定位置的元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 |
public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 |
public E peek() | 返回第一个元素。 |
public E element() | 返回第一个元素。 |
public E peekFirst() | 返回头部元素。 |
public E peekLast() | 返回尾部元素。 |
public E set(int index, E element) | 设置指定位置的元素。 |
public Object clone() | 克隆该列表。 |
public Iterator descendingIterator() | 返回倒序迭代器。 |
public int size() | 返回链表元素个数。 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 |
public Object[] toArray() | 返回一个由链表元素组成的数组。 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
示例:
package test1;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
public class TestLinkedList {
public static void main(String[] args) {
LinkedList<String> sites = new LinkedList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
System.out.println(sites);
// 使用 addFirst() 在头部添加元素
sites.addFirst("Wiki");
System.out.println(sites);
// 使用 addLast() 在尾部添加元素
sites.addLast("Wiki");
System.out.println(sites);
// 使用 removeFirst() 移除头部元素
sites.removeFirst();
System.out.println(sites);
// 使用 removeLast() 移除尾部元素
sites.removeLast();
System.out.println(sites);
// 使用 getFirst() 获取头部元素
System.out.println(sites.getFirst());
// 使用 getLast() 获取尾部元素
System.out.println(sites.getLast());
//删除并返回第一个元素
System.out.println(sites.poll());
System.out.println(sites.remove());
//判断是否含有某一元素
System.out.println(sites.contains("Google"));
//返回第一个元素
System.out.println(sites.peek());
System.out.println(sites.element());
//设置指定位置的元素
System.out.println(sites.set(0,"test"));
//遍历的四种方式
//(1)使用迭代器遍历
Iterator iterator = sites.iterator();
while (iterator.hasNext()) System.out.print (iterator.next()+" ");
//(2)使用列表迭代器遍历
System.out.println();
ListIterator<String> listIterator = sites.listIterator();
while(listIterator.hasNext()) System.out.print(listIterator.next() + " ");
//(3)使用size()和get()方法遍历 (for循环)
System.out.println();
for(int i = 0; i < sites.size(); i++) System.out.print(sites.get(i) + " ");
//使用增强for遍历
System.out.println();
for(String str : sites) System.out.print(str + " ");
}
}
输出结果:
[Google, Runoob, Taobao, Weibo]
[Wiki, Google, Runoob, Taobao, Weibo]
[Wiki, Google, Runoob, Taobao, Weibo, Wiki]
[Google, Runoob, Taobao, Weibo, Wiki]
[Google, Runoob, Taobao, Weibo]
Google
Weibo
Google
Runoob
false
Taobao
Taobao
Taobao
test Weibo
test Weibo
test Weibo
test Weibo
(2)ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList 继承了 AbstractList ,并实现了 List 接口。
使用场景:
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
实现的接口:
- List接口
- RandomAccess接口
- Cloneable接口
- Serializable接口
- 继承了AbstractList类
常用方法:
方法 | 描述 |
---|---|
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
toArray() | 将 arraylist 转换为数组 |
toString() | 将 arraylist 转换为字符串 |
ensureCapacity() | 设置指定容量大小的 arraylist |
lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
trimToSize() | 将 arraylist 中的容量调整为数组中的元素个数 |
removeRange() | 删除 arraylist 中指定索引之间存在的元素 |
replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
removeIf() | 删除所有满足特定条件的 arraylist 元素 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
示例:
public class TestArrayList {
public static void main(String[] args) {
ArrayList<String> sites = new ArrayList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
System.out.println(sites);
// 访问第二个元素
System.out.println(sites.get(1));
// 第一个参数为索引位置,第二个为要修改的值
sites.set(2, "Wiki");
System.out.println(sites);
//删除第四个元素
sites.remove(3);
System.out.println(sites);
//计算 ArrayList 中的元素数量
System.out.println(sites.size());
//字母排序
sites.add("Weibo");
sites.add("Google");
Collections.sort(sites);
System.out.println(sites);
//将 arraylist 转换为数组
System.out.println(sites.toArray());
//将 arraylist 转换为字符串
System.out.println(sites.toString());
//返回指定元素在 arraylist 中最后一次出现的位置
System.out.println(sites.lastIndexOf("Google"));
//查看 arraylist 是否包含指定元素
System.out.println(sites.contains("Weibo"));
//将给定的操作内容替换掉数组中每一个元素
sites.replaceAll(String::toUpperCase);
System.out.println(sites);
//遍历
//(1)使用迭代器遍历
Iterator iterator = sites.iterator();
while (iterator.hasNext()) System.out.print (iterator.next()+" ");
//(2)使用列表迭代器遍历
System.out.println();
ListIterator<String> listIterator = sites.listIterator();
while(listIterator.hasNext()) System.out.print(listIterator.next() + " ");
//(3)使用size()和get()方法遍历 (for循环)
System.out.println();
for(int i = 0; i < sites.size(); i++) System.out.print(sites.get(i) + " ");
//使用增强for遍历
System.out.println();
for(String str : sites) System.out.print(str + " ");
}
}
运行结果:
[Google, Runoob, Taobao, Weibo]
Runoob
[Google, Runoob, Wiki, Weibo]
[Google, Runoob, Wiki]
3
[Google, Google, Runoob, Weibo, Wiki]
[Ljava.lang.Object;@7f31245a
[Google, Google, Runoob, Weibo, Wiki]
1
true
[GOOGLE, GOOGLE, RUNOOB, WEIBO, WIKI]
GOOGLE GOOGLE RUNOOB WEIBO WIKI
GOOGLE GOOGLE RUNOOB WEIBO WIKI
GOOGLE GOOGLE RUNOOB WEIBO WIKI
GOOGLE GOOGLE RUNOOB WEIBO WIKI
Process finished with exit code 0
(3)Vector
Vector 类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的:
- Vector 是同步访问的。
- Vector 包含了许多传统的方法,这些方法不属于集合框架。
Vector 类支持 4 种构造方法:
- 第一种构造方法创建一个默认的向量,默认大小为 10:
Vector()
- 第二种构造方法创建指定大小的向量。
Vector(int size)
- 第三种构造方法创建指定大小的向量,并且增量用 incr 指定。增量表示向量每次增加的元素数目。
Vector(int size,int incr)
- 第四种构造方法创建一个包含集合 c 元素的向量:
Vector(Collection c)
常用方法:
序号 | 方法描述 |
---|---|
1 | void add(int index, Object element) 在此向量的指定位置插入指定的元素。 |
2 | boolean add(Object o) 将指定元素添加到此向量的末尾。 |
3 | boolean addAll(Collection c) 将指定 Collection 中的所有元素添加到此向量的末尾,按照指定 collection 的迭代器所返回的顺序添加这些元素。 |
4 | boolean addAll(int index, Collection c) 在指定位置将指定 Collection 中的所有元素插入到此向量中。 |
5 | void addElement(Object obj) 将指定的组件添加到此向量的末尾,将其大小增加 1。 |
6 | int capacity() 返回此向量的当前容量。 |
7 | void clear() 从此向量中移除所有元素。 |
8 | Object clone() 返回向量的一个副本。 |
9 | boolean contains(Object elem) 如果此向量包含指定的元素,则返回 true。 |
10 | boolean containsAll(Collection c) 如果此向量包含指定 Collection 中的所有元素,则返回 true。 |
11 | void copyInto(Object[] anArray) 将此向量的组件复制到指定的数组中。 |
12 | Object elementAt(int index) 返回指定索引处的组件。 |
13 | Enumeration elements() 返回此向量的组件的枚举。 |
14 | void ensureCapacity(int minCapacity) 增加此向量的容量(如有必要),以确保其至少能够保存最小容量参数指定的组件数。 |
15 | boolean equals(Object o) 比较指定对象与此向量的相等性。 |
16 | Object firstElement() 返回此向量的第一个组件(位于索引 0) 处的项)。 |
17 | Object get(int index) 返回向量中指定位置的元素。 |
18 | int hashCode() 返回此向量的哈希码值。 |
19 | int indexOf(Object elem) 返回此向量中第一次出现的指定元素的索引,如果此向量不包含该元素,则返回 -1。 |
20 | int indexOf(Object elem, int index) 返回此向量中第一次出现的指定元素的索引,从 index 处正向搜索,如果未找到该元素,则返回 -1。 |
21 | void insertElementAt(Object obj, int index) 将指定对象作为此向量中的组件插入到指定的 index 处。 |
22 | boolean isEmpty() 测试此向量是否不包含组件。 |
23 | Object lastElement() 返回此向量的最后一个组件。 |
24 | int lastIndexOf(Object elem) 返回此向量中最后一次出现的指定元素的索引;如果此向量不包含该元素,则返回 -1。 |
25 | int lastIndexOf(Object elem, int index) 返回此向量中最后一次出现的指定元素的索引,从 index 处逆向搜索,如果未找到该元素,则返回 -1。 |
26 | Object remove(int index) 移除此向量中指定位置的元素。 |
27 | boolean remove(Object o) 移除此向量中指定元素的第一个匹配项,如果向量不包含该元素,则元素保持不变。 |
28 | boolean removeAll(Collection c) 从此向量中移除包含在指定 Collection 中的所有元素。 |
29 | void removeAllElements() 从此向量中移除全部组件,并将其大小设置为零。 |
30 | boolean removeElement(Object obj) 从此向量中移除变量的第一个(索引最小的)匹配项。 |
31 | void removeElementAt(int index) 删除指定索引处的组件。 |
32 | protected void removeRange(int fromIndex, int toIndex) 从此 List 中移除其索引位于 fromIndex(包括)与 toIndex(不包括)之间的所有元素。 |
33 | boolean retainAll(Collection c) 在此向量中仅保留包含在指定 Collection 中的元素。 |
34 | Object set(int index, Object element) 用指定的元素替换此向量中指定位置处的元素。 |
35 | void setElementAt(Object obj, int index) 将此向量指定 index 处的组件设置为指定的对象。 |
36 | void setSize(int newSize) 设置此向量的大小。 |
37 | int size() 返回此向量中的组件数。 |
38 | List subList(int fromIndex, int toIndex) 返回此 List 的部分视图,元素范围为从 fromIndex(包括)到 toIndex(不包括)。 |
39 | Object[] toArray() 返回一个数组,包含此向量中以恰当顺序存放的所有元素。 |
40 | Object[] toArray(Object[] a) 返回一个数组,包含此向量中以恰当顺序存放的所有元素;返回数组的运行时类型为指定数组的类型。 |
41 | String toString() 返回此向量的字符串表示形式,其中包含每个元素的 String 表示形式。 |
42 | void trimToSize() 对此向量的容量进行微调,使其等于向量的当前大小。 |
示例:
public class TestVector {
public static void main(String args[]) {
// initial size is 3, increment is 2(创建一个大小为3,当快满时按2个元素大小的扩容向量)
Vector v = new Vector(3, 2);
System.out.println("Initial size: " + v.size());
System.out.println("Initial capacity: " +
v.capacity());
v.addElement(new Integer(1));
v.addElement(new Integer(2));
v.addElement(new Integer(3));
v.addElement(new Integer(4));
//向量大小
System.out.println("Capacity after four additions: " +
v.capacity());
//将指定的组件添加到此向量的末尾,将其大小增加 1。
v.addElement(new Double(5.45));
System.out.println("Current capacity: " +
v.capacity());
v.addElement(new Double(6.08));
v.addElement(new Integer(7));
System.out.println("Current capacity: " +
v.capacity());
v.addElement(new Float(9.4));
v.addElement(new Integer(10));
System.out.println("Current capacity: " +
v.capacity());
v.addElement(new Integer(11));
v.addElement(new Integer(12));
//输出第一个向量
System.out.println("First element: " +
(Integer)v.firstElement());
//输出最后一个向量
System.out.println("Last element: " +
(Integer)v.lastElement());
//是否包含3
if(v.contains(new Integer(3)))
System.out.println("Vector contains 3.");
// enumerate the elements in the vector.
//返回此向量的组件的枚举
Enumeration vEnum = v.elements();
System.out.println("\nElements in vector:");
while(vEnum.hasMoreElements())
System.out.print(vEnum.nextElement() + " ");
System.out.println();
}
}
运行结果:
Initial size: 0
Initial capacity: 3
Capacity after four additions: 5
Current capacity: 5
Current capacity: 7
Current capacity: 9
First element: 1
Last element: 12
Vector contains 3.
Elements in vector:
1 2 3 4 5.45 6.08 7 9.4 10 11 12
2、Set接口
(1)HashSet
特点:
- HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
- HashSet 允许有 null 值。
- HashSet 是无序的,即不会记录插入的顺序。
- 没有索引,没有带索引的方法,也不能使用普通的for遍历
- HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
- 底层是一个哈希表结构(查找快)
- HashSet 实现了 Set 接口。
去重原理:
重写了hashCode方法和equals方法,set加入一个对象,首先查看该对象的哈希值,然后看哈希表对应的哈希值是否有对象存储了,如果还没有那么就直接插入哈希表中;如果已经存储着相同哈希值的对象,那么就要使用equals方法比较是不是有相同的对象,如果没有则插入。
注意:哈希表在解决冲突问题的时候采用的是拉链法,在同一个哈希值存储的的元素个数小于8时使用链表,大于等于8就改成了红黑树(红黑树是一棵自平衡的二叉树)
序号 | 方法 |
1 | add(Object o)和addAll(Collection c)增加元素 |
2 | contains(Object o)和containsAll(Collection c)判断元素是否存在 |
3 | isEmpty()判断集合是否为空 |
4 | remove(Object o)和removeAll(Collection c)删除元素 |
5 | size()返回集合的大小 |
6 | clear()清空集合 |
7 | iterator()迭代器 |
8 | toArray()将内容转到数组中 |
示例:
package test1;
import java.util.HashSet;
import java.util.Iterator;
public class TestHashSet {
public static void main(String[] args) {
HashSet<String> sites = new HashSet<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
sites.add("Runoob");
// 重复的元素不会被添加
System.out.println(sites);
// 删除元素,删除成功返回 true,否则为 false
sites.remove("Taobao");
System.out.println(sites);
//计算大小
System.out.println(sites.size());
//判断是否包含某个元素
System.out.println(sites.contains("Baidu"));
//判空
System.out.println(sites.isEmpty());
//转换成数组
for(Object i : sites.toArray()) System.out.println(i);
//迭代
Iterator<String> it = sites.iterator();
while (it.hasNext()) System.out.print(it.next() + " ");
System.out.println();
//清除集合
sites.clear();
System.out.println(sites);
}
}
运行结果:
[Google, Runoob, Zhihu, Taobao]
[Google, Runoob, Zhihu]
3
false
false
Google
Runoob
Zhihu
Google Runoob Zhihu
[]
(二)Map接口
1、HashMap接口
特点:
- HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
- HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
- HashMap 是无序的,即不会记录插入的顺序。
- HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
- HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。
实现的接口:
- 继承AbstractMap
- Map 接口
- Cloneable接口
- Serializable接口
常用方法:
方法 | 描述 |
---|---|
clear() | 删除 hashMap 中的所有键/值对 |
clone() | 复制一份 hashMap |
isEmpty() | 判断 hashMap 是否为空 |
size() | 计算 hashMap 中键/值对的数量 |
put() | 将键/值对添加到 hashMap 中 |
putAll() | 将所有键/值对添加到 hashMap 中 |
putIfAbsent() | 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。 |
remove() | 删除 hashMap 中指定键 key 的映射关系 |
containsKey() | 检查 hashMap 中是否存在指定的 key 对应的映射关系。 |
containsValue() | 检查 hashMap 中是否存在指定的 value 对应的映射关系。 |
replace() | 替换 hashMap 中是指定的 key 对应的 value。 |
replaceAll() | 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。 |
get() | 获取指定 key 对应对 value |
getOrDefault() | 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 |
forEach() | 对 hashMap 中的每个映射执行指定的操作。 |
entrySet() | 返回 hashMap 中所有映射项的集合集合视图。 |
keySet() | 返回 hashMap 中所有 key 组成的集合视图。 |
values() | 返回 hashMap 中存在的所有 value 值。 |
merge() | 添加键值对到 hashMap 中 |
compute() | 对 hashMap 中指定 key 的值进行重新计算 |
computeIfAbsent() | 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap 中 |
computeIfPresent() | 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。 |
示例:
package test1;
import java.util.HashMap;
public class TestHashMap {
public static void main(String[] args) {
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, "Google");
Sites.put(2, "Runoob");
Sites.put(3, "Taobao");
Sites.put(4, "Zhihu");
System.out.println(Sites);
//使用 remove(key) 方法来删除 key 对应的键值对(key-value):
Sites.remove(4);
System.out.println(Sites);
//计算大小
System.out.println(Sites.size());
/**
* 迭代元素
* 只想获取 key,可以使用 keySet() 方法,然后可以通过 get(key) 获取对应的 value
* 如果你只想获取 value,可以使用 values() 方法
* */
// 输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}
// 返回所有 value 值
for(String value: Sites.values()) {
// 输出每一个value
System.out.print(value + ", ");
}
//删除所有键值对(key-value)可以使用 clear 方法
Sites.clear();
System.out.println(Sites);
}
}
输出结果:
{1=Google, 2=Runoob, 3=Taobao, 4=Zhihu}
{1=Google, 2=Runoob, 3=Taobao}
3
key: 1 value: Google
key: 2 value: Runoob
key: 3 value: Taobao
Google, Runoob, Taobao, {}
2、HashTable接口
概述:
- Hashtable是原始的java.util的一部分, 是一个Dictionary具体的实现 。
- Java 2 重构的Hashtable实现了Map接口,因此,Hashtable现在集成到了集合框架中。它和HashMap类很相似,但是它支持同步。
- 像HashMap一样,Hashtable在哈希表中存储键/值对。当使用一个哈希表,要指定用作键的对象,以及要链接到该键的值。然后,该键经过哈希处理,所得到的散列码被用作存储在该表中值的索引。
构造方法:
- 第一个是默认构造方法:
Hashtable()
- 第二个构造函数创建指定大小的哈希表:
Hashtable(int size)
- 第三个构造方法创建了一个指定大小的哈希表,并且通过fillRatio指定填充比例。填充比例必须介于0.0和1.0之间,它决定了哈希表在重新调整大小之前的充满程度:
Hashtable(int size,float fillRatio)
- 第四个构造方法创建了一个以M中元素为初始化元素的哈希表。哈希表的容量被设置为M的两倍。
Hashtable(Map m)
常用方法:
序号 | 方法描述 |
---|---|
1 | void clear( ) 将此哈希表清空,使其不包含任何键。 |
2 | Object clone( ) 创建此哈希表的浅表副本。 |
3 | boolean contains(Object value) 测试此映射表中是否存在与指定值关联的键。 |
4 | boolean containsKey(Object key) 测试指定对象是否为此哈希表中的键。 |
5 | boolean containsValue(Object value) 如果此 Hashtable 将一个或多个键映射到此值,则返回 true。 |
6 | Enumeration elements( ) 返回此哈希表中的值的枚举。 |
7 | Object get(Object key) 返回指定键所映射到的值,如果此映射不包含此键的映射,则返回 null. 更确切地讲,如果此映射包含满足 (key.equals(k)) 的从键 k 到值 v 的映射,则此方法返回 v;否则,返回 null。 |
8 | boolean isEmpty( ) 测试此哈希表是否没有键映射到值。 |
9 | Enumeration keys( ) 返回此哈希表中的键的枚举。 |
10 | Object put(Object key, Object value) 将指定 key 映射到此哈希表中的指定 value。 |
11 | void rehash( ) 增加此哈希表的容量并在内部对其进行重组,以便更有效地容纳和访问其元素。 |
12 | Object remove(Object key) 从哈希表中移除该键及其相应的值。 |
13 | int size( ) 返回此哈希表中的键的数量。 |
14 | String toString( ) 返回此 Hashtable 对象的字符串表示形式,其形式为 ASCII 字符 ", " (逗号加空格)分隔开的、括在括号中的一组条目。 |
示例:
package test1;
import java.util.Enumeration;
import java.util.Hashtable;
public class TestHashTable {
public static void main(String args[]) {
// Create a hash map
Hashtable balance = new Hashtable();
Enumeration names;
String str;
double bal;
//将指定 key 映射到此哈希表中的指定 value。
balance.put("Zara", new Double(3434.34));
balance.put("Mahnaz", new Double(123.22));
balance.put("Ayan", new Double(1378.00));
balance.put("Daisy", new Double(99.22));
balance.put("Qadir", new Double(-19.08));
// 返回此哈希表中的键的枚举。
names = balance.keys();
while(names.hasMoreElements()) {
str = (String) names.nextElement();
System.out.println(str + ": " +
balance.get(str));
}
System.out.println();
// 返回指定键所映射到的值
bal = ((Double)balance.get("Zara")).doubleValue();
balance.put("Zara", new Double(bal+1000));
System.out.println("Zara's new balance: " +
balance.get("Zara"));
}
}
运行结果:
Qadir: -19.08
Zara: 3434.34
Mahnaz: 123.22
Daisy: 99.22
Ayan: 1378.0
Zara's new balance: 4434.34
3、TreeMap接口
概述:
- TreeMap存储K-V键值对,通过红黑树(R-B tree)实现;
- TreeMap继承了NavigableMap接口,NavigableMap接口继承了SortedMap接口,可支持一系列的导航定位以及导航操作的方法,但只是提供了接口,需要TreeMap自己去实现;
- TreeMap实现了Cloneable接口,可被克隆,实现了Serializable接口,可序列化;
- TreeMap因为是通过红黑树实现,红黑树结构天然支持排序,默认情况下通过Key值的自然顺序进行排序;
实现接口:
- Map接口
- 继承了NavigableMap接口
- SortedMap接口
- Cloneable接口
- Serializable接口
构造方法:
- TreeMap()创建一个空的TreeMap,并且按照key的自然升序排序;
- TreeMap(Comparatorcomparator)创建一个空的TreeMap,并且指定排序方法;
- TreeMap(Mapm)根据给定的Map创建一个TreeMap,按照key的自然升序排序;
- TreeMap(SortedMapm)根据一个有序的Map创建一个TreeMap,顺序与原Map相同。
常用方法:
序号 | 方法 |
1 | public V put(K key,V value)添加一对键值对 |
2 | public void putAll(Mapmap)添加一个map的所有键值对 |
3 | public V remove(Object key)删除对应的键值对 |
4 | public void clear()删除所有元素 |
5 | public Map.EntryceilingEntry(K key)返回map中键值不小于参数key的最小键值对应的键值 |
6 | public K ceilingKey(K key)返回map中键值不小于参数key的最小键值 |
7 | public final boolean containsKey(Object key)判断是否含有某一键值 |
8 | public boolean containsValue(Object value)判断是否含有某一value |
9 | public NavigableMapdescendingMap()返回一个降序排列的Map |
10 | public NavigableSetdescendingKeySet()返回一个降序排列的由键名组成的Set |
11 | public Set>entrySet()返回由原Map的键值对组成的Set |
12 | public K firstKey()返回第一个key |
13 | public Map.firstEntry()返回第一个键值对 |
14 | public K floorKey(K key)返回Map中不大于指定key的最大key值 |
15 | public Map.EntryfloorEntry(K key)返回Map中不大于指定key的最大key值所对应的键值对 |
16 | public V get(Object key)取出指定key对应的键值对 |
17 | public SortedMapheadMap(K toKey)返回key小于指定key的排序好的Map |
18 | public NavigableMapheadMap(K toKey,boolean inclusive)返回key小于或小于等于指定key |
19 | public K higherKey(K key)返回key严格大于指定key的最小键 |
20 | public Map.EntryhigherEntry(K key)返回key严格大于指定key的最小键值对 |
21 | public SetkeySet()返回由key组成的Set |
22 | public K lastKey()返回最后一个key |
23 | public Map.EntrylastEntry()返回最后一组键值对 |
24 | public K lowerKey(K key)返回key严格小于指定值的最大键 |
25 | public Map.EntrylowerEntry(K key)返回key严格小于指定值的最大键值对 |
26 | public NavigableMapsubMap(K fromKey,boolean fromInclusive,K toKey,boolean toInclusive)返回key在指定范围内的子Map |
27 | public SortedMapsubMap(K fromKey,K toKey)返回key在指定范围内的子Map |
28 | public NavigableMaptailMap(K fromKey,boolean inclusive)返回key小于或小于等于指定key的排序好的Map |
29 | public SortedMaptailMap(K fromKey)返回key大于指定key的排序好的Map |
30 | public V replace(K key,V value)修改一对键值对 |
31 | public boolean replace(K key,V oldValue,V newValue)如果键值对的原值为指定值,则修改,否则不修改 |
32 | public void replaceAll(BiFunctionfunction)按照指定函数运算修改所有键值对 |
33 | public Object clone()克隆TreeMap |
34 | public Comparatorcomparator()返回该TreeMap的比较器 |
35 | keySet(),entrySet()遍历倒序的descendingKeySet() |
36 | subMap(),tailMap(),headMap() |
示例:
package test1;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class TestTreeMap {
public static void main(String[] args) {
TreeMap<Integer, String> sites = new TreeMap<Integer, String>();
// 添加键值对
sites.put(1, "Google");
sites.put(2, "Runoob");
sites.put(3, "Taobao");
sites.put(4, "Zhihu");
System.out.println(sites);
//使用 remove(key) 方法来删除 key 对应的键值对(key-value):
sites.remove(4);
System.out.println(sites);
//计算大小
System.out.println(sites.size());
//判断是否含有某一键值
System.out.println(sites.containsKey(1));
//判断是否含有某一value
System.out.println(sites.containsValue("Goodle"));
//返回一个降序排列的Map
System.out.println(sites.navigableKeySet());
//返回第一个key
System.out.println(sites.firstKey());
//返回第一个键值对
System.out.println(sites.firstEntry());
//修改一对键值对
sites.replace(1,"Baidu");
System.out.println(sites);
//遍历
//第一种方式
for(Map.Entry entry : sites.entrySet()) System.out.print(entry + " ");
System.out.println();
//第二种方式
Iterator iter = sites.entrySet().iterator();
while (iter.hasNext()) System.out.print(iter.next() + " ");
System.out.println();
//清除
sites.clear();
}
}
输出结果:
{1=Google, 2=Runoob, 3=Taobao, 4=Zhihu}
{1=Google, 2=Runoob, 3=Taobao}
3
true
false
[1, 2, 3]
1
1=Google
{1=Baidu, 2=Runoob, 3=Taobao}
1=Baidu 2=Runoob 3=Taobao
1=Baidu 2=Runoob 3=Taobao
Process finished with exit code 0
二、Object、泛型与序列化
(一)Object
1、概述
Java Object 类是所有类的父类,位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
Object 类可以显示继承,也可以隐式继承,以下两种方式时一样:
显示继承:
public class Runoob extends Object{ }
隐式继承:
public class Runoob { }
2、构造函数
Object() 构造一个新对象。
3、常用方法
序号 | 方法 & 描述 |
---|---|
1 | protected Object clone() 创建并返回一个对象的拷贝 |
2 | boolean equals(Object obj) 比较两个对象是否相等 |
3 | protected void finalize() 当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法。 |
4 | Class<?> getClass() 获取对象的运行时对象的类 |
5 | int hashCode() 获取对象的 hash 值 |
6 | void notify() 唤醒在该对象上等待的某个线程 |
7 | void notifyAll() 唤醒在该对象上等待的所有线程 |
8 | String toString() 返回对象的字符串表示形式 |
9 | void wait() 让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。 |
10 | void wait(long timeout) 让当前线程处于等待(阻塞)状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数设置的timeout超时时间。 |
11 | void wait(long timeout, int nanos) 与 wait(long timeout) 方法类似,多了一个 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。 |
(二)泛型
1、概述
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
2、泛型方法
定义泛型方法的规则:
- 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的 <E>)。
- 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
- 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
- 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像 int、double、char 等)。
java 中泛型标记符:
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
- ? - 表示不确定的 java 类型
示例:
public class GenericMethodTest
{
// 泛型方法 printArray
public static < E > void printArray( E[] inputArray )
{
// 输出数组元素
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] )
{
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "整型数组元素为:" );
printArray( intArray ); // 传递一个整型数组
System.out.println( "\n双精度型数组元素为:" );
printArray( doubleArray ); // 传递一个双精度型数组
System.out.println( "\n字符型数组元素为:" );
printArray( charArray ); // 传递一个字符型数组
}
}
运行结果:
整型数组元素为:
1 2 3 4 5
双精度型数组元素为:
1.1 2.2 3.3 4.4
字符型数组元素为:
H E L L O
有界类型的参数:
可能有时候,你会想限制那些被允许传递到一个类型参数的类型种类范围。例如,一个操作数字的方法可能只希望接受Number或者Number子类的实例。这就是有界类型参数的目的。
要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。
public class MaximumTest
{
// 比较三个值并返回最大值
public static <T extends Comparable<T>> T maximum(T x, T y, T z)
{
T max = x; // 假设x是初始最大值
if ( y.compareTo( max ) > 0 ){
max = y; //y 更大
}
if ( z.compareTo( max ) > 0 ){
max = z; // 现在 z 更大
}
return max; // 返回最大对象
}
public static void main( String args[] )
{
System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",
3, 4, 5, maximum( 3, 4, 5 ) );
System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",
6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear",
"apple", "orange", maximum( "pear", "apple", "orange" ) );
}
}
运行结果:
3, 4 和 5 中最大的数为 5
6.6, 8.8 和 7.7 中最大的数为 8.8
pear, apple 和 orange 中最大的数为 pear
3、泛型类
泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
//泛型类:Integer类型
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("菜鸟教程"));
System.out.printf("整型值为 :%d\n\n", integerBox.get());
System.out.printf("字符串为 :%s\n", stringBox.get());
}
}
运行结果:
整型值为 :10
字符串为 :菜鸟教程
4、类型通配符
(1)类型通配符一般是使用 ? 代替具体的类型参数。例如 List<?> 在逻辑上是 List<String>,List<Integer> 等所有 List<具体类型实参> 的父类。
(2)类型通配符上限通过形如List来定义,如此定义就是通配符泛型值接受Number及其下层子类类型。
(三)序列化
1、序列化条件
- 该类必须实现 java.io.Serializable 接口。
- 该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。
2、序列化作用
- 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
- 在网络上传送对象的字节序列。
3、序列化与反序列化
- 序列化:把Java对象转换为字节序列的过程。
- 反序列化:把字节序列恢复为Java对象的过程。
4、序列化与反序列化步骤
序列化步骤
- 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
- 通过对象输出流的writeObject()方法写对象。
反序列化步骤
- 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
- 通过对象输入流的readObject()方法读取对象。