Java集合框架

概述

​ 一方面, 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另一方面,使用Array存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引用放入容器中。

​ 对于数组存储对象的弊端:

  • 一旦创建,其长度不可变
  • 真实的数组存放的对象的个数是不可知的

Java 集合类:可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组。

分类

​ Java 集合可分为 Collection 和 Map 两种体系

  • Collection接口:

    • Set:元素无序、不可重复的集合 — 类似高中的“集合”
    • List:元素有序,可重复的集合 — “动态”数组
  • Map接口:具有映射关系“key-value对”的集合 — 类似于高中的“函数”

Collection接口继承树

Map接口继承树

Collection接口

概述

  • Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
  • JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。
  • 在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 Java5 增加了泛型以后,Java 集合可以记住容器中对象的数据类型

接口方法

size( )

​ 返回集合中元素的个数。

add(Object obj)

​ 向集合中添加一个元素。

addAll(Collection c)

​ 将形参c中包含的所有元素添加到当前集合中。

isEmpty( )

​ 判断集合是否为空。

clear( )

​ 清空集合元素。

contains(Object obj)

​ 判断此集合中是否包含指定的obj元素。

​ 判断的依据:根据元素所在类的equals( )方法进行判断。

​ 明确:如果存入集合中的元素是自定义类的对象,要求:自定义类要重写equals( )方法!

containsAll(Collection c)

​ 判断当前集合中是否包含c中所有的元素。

retainAll(Collection c)

​ 求当前集合与c中共有的元素,返回给当前集合。

remove(Object obj)

​ 在当前元素中删除指定的obj元素。

removeAll(Collection c)

​ 从当前集合中删除包含在c中的元素。

equals(Object obj)

​ 判断两个集合中所有元素是否相同。

hashCode( )

​ 返回此集合的哈希值。

toArray( )

​ 将集合转化为数组。

toArray(T[] a)

​ 将集合转化为数组。返回数组的运行时类型与指定数组的运行时类型相同。

iterator( )

​ 返回在此集合的元素上进行迭代的迭代器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class TestIterator {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add("小新");
collection.add("小伟");
collection.add("小鑫");
Iterator iterator = collection.iterator();

// 方式一:一个一个输出
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());

// 方式二:使用for循环
for (int i = 0; i < collection.size(); i++){
System.out.println(iterator.next());
}

// 方式三:使用hasNext()
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}

遍历集合元素

Iterator接口遍历

概述

​ Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素

  • 所有实现了Collection接口的集合类都有一个iterator( )方法,用以返回一个实现了Iterator接口的对象
  • Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。

示例

1
2
3
4
Iterator iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}

Iterator接口的方法

在调用it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常。

foreach循环遍历

概述

​ Java 5 提供了 foreach 循环迭代访问 Collection。

面试题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestFor {
public static void main(String[] args){
String[] str = new String["aa","bb","cc"];
for(String myStr : str){
myStr = "00";
System.out.println(myStr);
}
for(int i = 0;i < str.length;i++){
System.out.println(str[i]);
}
}
}
// 00
// 00
// 00
// aa
// bb
// cc

Collection子接口之一: List接口

概述

  • List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  • JDK API中List接口的实现类常用的有:ArrayList、LinkedList 和 Vector。

常用方法

​ List 集合里添加了一些根据索引来操作集合元素的方法:

  • void add(int index, Object ele)
  • boolean addAll(int index, Collection eles)
  • Object get(int index)
  • int indexOf(Object obj)
  • int lastIndexOf(Object obj)
  • Object remove(int index)
  • Object set(int index, Object ele)
  • List subList(;int fromIndex, int toIndex)

List实现类: ArrayList

  • ArrayList 是 List 接口的典型实现类
  • 本质上,ArrayList是对象引用的一个变长数组
  • ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector
  • Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合

List实现类: LinkedList

  • 对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
  • 新增方法:
    • void addFirst(Object obj)
    • void addLast(Object obj)
    • Object getFirst()
    • Object getLast()
    • Object removeFirst()
    • Object removeLast()

List 实现类之三: Vector

  • Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的
  • 在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。
  • 新增方法:
    • void addElement(Object obj)
    • void insertElementAt(Object obj,int index)
    • void setElementAt(Object obj,int index)
    • void removeElement(Object obj)
    • void removeAllElements()

Collection子接口之二: Set接口

概述

  • Set 接口是Collection的子接口,set接口没有提供额外的方法
  • Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败
  • Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法

Set实现类之一: HashSet

特点

  • HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。

  • HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能

  • HashSet 具有以下特点:

    • 不能保证元素的排列顺序
    • HashSet 不是线程安全的
    • 集合元素可以是 null
  • 当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。

  • HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

hashCode( ) 方法

​ 如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。

  • 对于存放在Set容器中的对象,对应的类一定要重写equals()hashCode(Object obj)方法,以实现对象相等规则。
  • 重写 hashCode() 方法的基本原则
    • 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值
    • 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等
    • 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值

Set实现类之二: LinkedHashSet

  • LinkedHashSet 是 HashSet 的子类
  • LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的
  • LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能
  • LinkedHashSet 不允许集合元素重复

Set实现类之三: TreeSet

概述

  • 向TreeSet中添加的元素必须是同一类型的
  • 不允许元素重复
  • 可以按照添加进集合中的元素的指定顺序遍历,例如String、包装类等默认按照从小到大的顺序遍历
  • 当自定义类没有实现Comparable接口时,向TreeSet中添加自定义类对象时,会报ClassCastException异常
  • TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态
    • Comparator comparator()
    • Object first()
    • Object last()
    • Object lower(Object e)
    • Object higher(Object e)
    • SortedSet subSet(fromElement, toElement)
    • SortedSet headSet(toElement)
    • SortedSet tailSet(fromElement)

​ TreeSet 两种排序方法:自然排序定制排序默认情况下,TreeSet 采用自然排序。

自然排序

自然排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序排列。

  • 如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。

  • 实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。

  • Comparable 的典型实现

    • BigDecimal、BigInteger 以及所有的数值型对应的包装类:按它们对应的数值大小进行比较
    • Character:按字符的 unicode值来进行比较
    • Boolean:true 对应的包装类实例大于 false 对应的包装类实例
    • String:按字符串中字符的 unicode 值进行比较
    • Date、Time:后边的时间、日期比前面的时间、日期大

​ 向 TreeSet 中添加元素时,只有第一个元素无须比较compareTo()方法,后面添加的所有元素都会调用compareTo()方法进行比较。

  • 因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象

  • 对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 方法比较返回值

  • 当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0

定制排序

​ TreeSet 的自然排序是根据集合元素的大小,进行元素升序排列。如果需要定制排序,比如降序排列,可通过Comparator接口的帮助,需要重写compare(T o1,T o2)方法。

  • 利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
  • 要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。此时,仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。
  • 使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0。

练习

  • 定义一个Employee类,该类包含:private成员变量name, age, birthday,其中 birthday 为 MyDate 类的对象;并为每一个属性定义 getter, setter 方法;并重写 toString 方法输出 name, age, birthday。
  • MyDate类包含:private成员变量month, day, year;并为每一个属性定义 getter, setter 方法;
  • 创建该类的 5 个对象,并把这些对象放入 TreeSet 集合中(下一章:TreeSet 需使用泛型来定义)。分别按以下两种方式对集合中的元素进行排序,并遍历输出:
    • 使 Employee 实现 Comparable 接口,并按 name 排序
    • 创建 TreeSet 时传入 Comparator对象,按生日日期的先后排序。

​ 提示:Employee类是否需要重写equals()方法?MyDate类呢?——需要

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.util.Objects;

public class Employee implements Comparable{
private String name;
private Integer age;
private MyDate birthday;

public Employee(String name, Integer age, MyDate birthday) {
super();
this.name = name;
this.age = age;
this.birthday = birthday;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public MyDate getBirthday() {
return birthday;
}

public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}

@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}

@Override
public int compareTo(Object o) {
if (o instanceof Employee){
Employee e = (Employee) o;
return this.name.compareTo(e.name);
}
return 0;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee)) return false;
Employee employee = (Employee) o;
return Objects.equals(getName(), employee.getName()) && Objects.equals(getAge(), employee.getAge()) && Objects.equals(getBirthday(), employee.getBirthday());
}

@Override
public int hashCode() {
return Objects.hash(getName(), getAge(), getBirthday());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.Objects;

public class Employee2{
private String name;
private Integer age;
private MyDate birthday;

public Employee2(String name, Integer age, MyDate birthday) {
super();
this.name = name;
this.age = age;
this.birthday = birthday;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public MyDate getBirthday() {
return birthday;
}

public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}

@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee2)) return false;
Employee2 employee2 = (Employee2) o;
return Objects.equals(getName(), employee2.getName()) && Objects.equals(getAge(), employee2.getAge()) && Objects.equals(getBirthday(), employee2.getBirthday());
}

@Override
public int hashCode() {
return Objects.hash(getName(), getAge(), getBirthday());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.Objects;

public class MyDate {
private Integer year;
private Integer month;
private Integer day;

public MyDate(Integer year, Integer month, Integer day) {
super();
this.year = year;
this.month = month;
this.day = day;
}

public Integer getYear() {
return year;
}

public void setYear(Integer year) {
this.year = year;
}

public Integer getMonth() {
return month;
}

public void setMonth(Integer month) {
this.month = month;
}

public Integer getDay() {
return day;
}

public void setDay(Integer day) {
this.day = day;
}

@Override
public String toString() {
return "MyDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MyDate)) return false;
MyDate myDate = (MyDate) o;
return Objects.equals(getYear(), myDate.getYear()) && Objects.equals(getMonth(), myDate.getMonth()) && Objects.equals(getDay(), myDate.getDay());
}

@Override
public int hashCode() {
return Objects.hash(getYear(), getMonth(), getDay());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TestTreeSet {
public static void main(String[] args) {

// 1、自然排序
// Employee employee = new Employee("小新",22,new MyDate(1999,10,29));
// Employee employee2 = new Employee("小鑫",24,new MyDate(1997,6,13));
// Employee employee3 = new Employee("小伟",21,new MyDate(2000,10,28));
// Employee employee4 = new Employee("小宇",23,new MyDate(1998,7,12));
// Employee employee5 = new Employee("小创",22,new MyDate(1999,3,18));
//
// TreeSet treeSet = new TreeSet();
// treeSet.add(employee);
// treeSet.add(employee2);
// treeSet.add(employee3);
// treeSet.add(employee4);
// treeSet.add(employee5);
//
// Iterator iterator = treeSet.iterator();
// while (iterator.hasNext()){
// System.out.println(iterator.next());
// }


// 2、定制排序
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Employee2 && o2 instanceof Employee2){
Employee2 e1 = (Employee2) o1;
Employee2 e2 = (Employee2) o2;
MyDate birthday1 = e1.getBirthday();
MyDate birthday2 = e2.getBirthday();
if (birthday1.getYear() != birthday2.getYear()){
return birthday1.getYear() - birthday2.getYear();
}
else {
if (birthday1.getMonth() != birthday2.getMonth()){
return birthday1.getMonth() - birthday2.getMonth();
}
else {
return birthday1.getDay() - birthday2.getDay();
}
}
}
return 0;
}
};
Employee2 employee = new Employee2("小新",22,new MyDate(1999,10,29));
Employee2 employee2 = new Employee2("小鑫",24,new MyDate(1997,6,13));
Employee2 employee3 = new Employee2("小伟",21,new MyDate(2000,10,28));
Employee2 employee4 = new Employee2("小宇",23,new MyDate(1998,7,12));
Employee2 employee5 = new Employee2("小创",22,new MyDate(1999,3,18));

TreeSet treeSet = new TreeSet(comparator);
treeSet.add(employee);
treeSet.add(employee2);
treeSet.add(employee3);
treeSet.add(employee4);
treeSet.add(employee5);

Iterator iterator = treeSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}

Map接口

概述

Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value

  • Map 中的 key 和 value 都可以是任何引用类型的数据
  • Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()equals()方法
  • 常用String类作为Map的“键”
  • key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value

Map体系继承树

Map常用方法

  • 添加、删除操作:

    • Object put(Object key,Object value)
    • Object remove(Object key)
    • void putAll(Map t)
    • void clear()
  • 元视图操作的方法:

    • Set keySet()
    • Collection values()
    • Set entrySet()
  • 元素查询的操作:

    • Object get(Object key)
    • boolean containsKey(Object key)
    • boolean containsValue(Object value)
    • int size()
    • boolean isEmpty()
    • boolean equals(Object obj)

Map实现类: HashMap

  • Map接口的常用实现类:HashMap、TreeMap和Properties
  • HashMap是 Map 接口使用频率最高的实现类
  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序
  • HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等
  • HashMap 判断两个 value 相等的标准是:两个 value 通过 equals() 方法返回 true

如何遍历Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.util.*;

public class TestMap {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("姓名","小新");
map.put("性别","男");
map.put("年龄",22);
map.put("身高",184);

// 1、遍历Key集
Set set = map.keySet();
for (Object obj : set){
System.out.println(obj);
}

// 2、遍历Values集
Collection collection = map.values();
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}

// 3、遍历key-value
//方法一
Set set1 = map.keySet();
for (Object obj : set1){
System.out.println(obj + ":" + map.get(obj));
}
//方法二
Set set2 = map.entrySet();
for (Object obj : set2){
Map.Entry entry = (Map.Entry)obj;
// System.out.println(entry.getKey() + ":" + entry.getValue());
System.out.println(entry);
}

}
}

Map实现类: LinkedHashMap

  • LinkedHashMap 是 HashMap 的子类
  • 与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

Map实现类: TreeMap

  • TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态

  • TreeMap 的 Key 的排序:

    • 自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
    • 定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
  • TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0

  • 若使用自定义类作为TreeMap的key,所属类需要重写equals()hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0

Map实现类: Hashtable

  • Hashtable是个古老的 Map 实现类,线程安全
  • 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
  • 与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
  • Hashtable判断两个key相等、两个value相等的标准,与hashMap一致

子类Properties

  • Properties 类是 Hashtable 的子类,该对象用于处理属性文件
  • 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型
  • 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class TestProperties {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream(new File("/Users/liuwq/Documents/IDEA/java/src/L07/exer3/jdbc.properties")));
String str = properties.getProperty("user");
String str2 = properties.getProperty("password");
System.out.println("user=" + str);
System.out.println("password=" + str2);
}
}

Collections工具类

​ Collections 是一个操作 Set、List 和 Map 等集合的工具类,Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变对集合对象实现同步控制等方法。

常用方法

  • 排序操作:(均为static方法)

    • reverse(List):反转 List 中元素的顺序
    • shuffle(List):对 List 集合元素进行随机排序
    • sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
    • sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
    • swap(List,int,int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
  • 查找、替换

    • Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
    • Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
    • Object min(Collection)
    • Object min(Collection,Comparator)
    • int frequency(Collection,Object):返回指定集合中指定元素的出现次数
    • void copy(List dest,List src):将src中的内容复制到dest中
    • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

同步控制

​ Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。

Enumeration

​ Enumeration 接口是 Iterator 迭代器的 “古老版本”

1
2
3
4
5
Enumeration stringEnum = new StringTokenizer("a-b*c-d-e-g", "-");
while(stringEnum.hasMoreElements()){
Object obj = stringEnum.nextElement();
System.out.println(obj);
}

面试题

  • Collection 和 Collections 的区别
    答:Collection是集合类的上级接口,继承他的接口主要有 Set 和 List。Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

  • Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别
    答:Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等,equals()和==方法决定引用值是否指向同一对象,equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

  • List, Set, Map是否继承自Collection接口
    答: List,Set是,Map不是

  • 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对
    答:不对,有相同的hash code

  • 说出ArrayList,Vector,LinkedList的存储性能和特性
    答:ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

  • HashMap和Hashtable的区别
    答:HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。
       HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
       HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 
       Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
       最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要
    
    自己为它的方法实现同步,而 HashMap 就必须为之提供外同步。
       Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异
    

  • ArrayList和Vector的区别,HashMap和Hashtable的区别
    答:就ArrayList与Vector主要从二方面来说:

    1. 同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的
    2. 数据增长:当需要增长时,Vector默认增长为原来一倍,而ArrayList却是原来的一半

    就HashMap与HashTable主要从三方面来说:

    1. 历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现
    2. 同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的
    3. 值:只有HashMap可以让你将空值作为一个表的条目的key或value