第十章集合类
10.1 集合概述
Java.util包中提供了一些集合类,这些集合类又被称为容器,集合类与数组的不同之处是,数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型的数组,集合用来存放对象的引用。
常用的的集合有List集合、Set集合和Map集合,其中List与Set继承了Collection接口
10.2 Collection接口
Collection 接口时层次结构中的根接口。构成Collection的单位称为元素
10.3 List集合
List接口继承了Collection接口以及List接口的所有实现类。
10.3.1 List接口
List接口继承了Collection接口
10.3.2 List接口的实现类
List接口由于不能直接实例化
(1)ArrayList类的优点时实现了可变数组,允许保存所有元素
(2)LinkedList类采用链表结构保存对象,这种结构的优点是便于向集合中插入和删除对象
List<E> list = new ArrayList<>();
List<E> list = new LinkedList<>();
package ten;
import java.util.*;
public class ListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String> list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
int i = (int) (Math.random()*list.size());
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));
}
}
}
随机获取数组中的元素:b
将索引是‘2’的元素从数组移除后,数组中的元素是:
a
b
10.3.3 Iterator 迭代器
在Java.util包中提供了一个Iterator接口,该接口是一个专门对Collection进行迭代的迭代器。
hasNext():如果迭代器指向位置后面还有元素,则返回 true,否则返回false
next():返回集合中Iterator指向位置后面的元素
remove():删除集合中Iterator指向位置后面的元素
ListIterator迭代器包含的方法有:
add(E e): 将指定的元素插入列表,插入位置为迭代器当前位置之前
hasNext():以正向遍历列表时,如果列表迭代器后面还有元素,则返回 true,否则返回false
hasPrevious():如果以逆向遍历列表,列表迭代器前面还有元素,则返回 true,否则返回false
next():返回列表中ListIterator指向位置后面的元素
nextIndex():返回列表中ListIterator所需位置后面元素的索引
previous():返回列表中ListIterator指向位置前面的元素
previousIndex():返回列表中ListIterator所需位置前面元素的索引
remove():从列表中删除next()或previous()返回的最后一个元素(有点拗口,意思就是对迭代器使用hasNext()方法时,删除ListIterator指向位置后面的元素;当对迭代器使用hasPrevious()方法时,删除ListIterator指向位置前面的元素)
set(E e):从列表中将next()或previous()返回的最后一个元素返回的最后一个元素更改为指定元素e
package ten;
import java.util.*;
public class IteratorTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
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);
}
}
}
a
b
c
10.4 Set集合
Set集合中的对象不按特定的方式排序,只是简单地把对象放进集合中,但Set集合中不能包含重复对象
10.4.1 Set接口
Set接口是一个不包含重复元素的集合,由于其继承Collection接口,因此包含Collection接口所有方法。
10.4.2 Set接口的实现类
Set接口常用的实现类有HashSet类与TreeSet类
(1)HashSet是Set接口的一个实现类,它不允许有重复元素。
(2)TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此,TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可以制定排序规则。
first()和last()方法
first() - 返回集合的第一个元素
last() - 返回集合的最后一个元素
headSet(),tailSet()和subSet()方法
headSet(element,booleanValue)
headSet()方法返回指定元素(作为参数传递)之前的树集的所有元素。booleanValue参数是可选的。默认值为false。
如果booleanValue的值为true,则该方法返回指定元素之前的所有元素,包括指定元素。
subSet(e1,bv1,e2,bv2)
subSet()方法返回e1和e2之间的所有元素,包括e1。bv1和bv2是可选参数。 bv1的默认值为true,bv2的默认值为false。
如果将false作为bv1传递,则该方法返回e1和e2之间的所有元素,而不包括e1。
如果将true作为bv2传递,则该方法返回e1和e2之间的所有元素,包括e1。
package ten;
import java.util.*;
public class HashSetTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Set set = new HashSet();
set.add("c");
set.add("c");
set.add("a");
set.add("b");
Iterator<String> it = set.iterator();
while (it.hasNext()){
String str = (String) it.next();
System.out.println(str);
}
}
}
a
b
c
10.5 Map集合
10.5.1 Map接口
Map接口提供了将key映射到值的对象。一个映射不能包含重复的key,每个key最多只能映射一个值。
10.5.2 Map接口的实现类
HashMap
概述
HashMap 是Map 的子类,此类的定义如下:
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
此类继承了AbstractMap 类,同时可以被克隆,可以被序列化下来。
特点
HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()
所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()
一个key-value构成一个entry
所有的entry构成的集合是Set:无序的、不可重复的
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。
HashMap的存储结构
JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。
HashMap的存储结构示意图
HashMap源码中的重要成员属性
常量
ULT_INITIAL_CAPACITY : HashMap的默认容量,16
MAXIMUM_CAPACITY : HashMap的最大支持容量,2^30
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子
TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树
UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转化为链表
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量。(当桶中Node的数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行。扩容操作这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD的4倍。)
变量
entrySet:存储具体元素的集
size:HashMap中存储的键值对的数量
modCount:HashMap扩容和结构改变的次数。
threshold:扩容的临界值,=容量*填充因子
loadFactor:填充因子
package ten;
import java.util.*;
public class HashMapTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<>();
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();
Iterator<String> it = set.iterator();
System.out.println("key的值");
while(it.hasNext()){
System.out.println(it.next() + "\t");
}
Collection<String> coll = map.values();
it = coll.iterator();
System.out.println("\nvalues值:");
while(it.hasNext()){
System.out.println(it.next() + "\t");
}
}
}
key的值
ISBN-978756
ISBN-978654
ISBN-978893
ISBN-978361
values值:
21天学Java
Java从入门到精通
21天学Android
Android从入门到精通
10.6 集合使用场合
HashTable,Vector类是同步的,而HashMap,ArrayList不是同步的。 因此当在多线程的情况下,应使用 HashTable和 Vector,相反则应使用HashMap,ArrayList.如果需要使用同步的集合可以使用 Collections.synchronizedList(List<T> list)得到同步的 List,Collections.synchronizedMap(Map<K,V> m) 的到同步的Map,也可以由Collections.synchronizedSet(Set<T> s)得到同步的Set,但他们的效率稍低.另外在除需要排序时使用TreeSet,TreeMap外,都应使用HashSet,HashMap,因为他们 的效率更高。ArrayList 和LinkList 的对比:ArrayList 由数组构建, LinkList由双向链表构建,因此在程序要经常添加,删除元素时速度要快些,最好使用LinkList,而其他情况下最好使用ArrayList.因 为他提供了更快的随机访问元素的方法。
在需要使用栈时,应使用LinkList 类来构件,不应使用Stack,因为Stack继承自Vector,包含方法elementAt(int indext),可以取得任意位置的对象,因此破坏了栈的机制.