一、Set、List、Map的定义
1.什么是set?
(1)Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面List有两个不同的List。实际上Set就是Collection,只是行为不同(这是继承与多态思想的典型应用:表现不同的行为)。
Set不保存重复的元素(至于如何判断元素相同则较为负责)。
(2)Set: 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。
TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。
LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
(3)Set的用法:存放的是对象的引用,没有重复对象。
实例:
Set set = new HashSet();
String s1 = new String("hello");
String s2 = s1;
String s3 = new String("world");
set.add(s1);
set.add(s2);
set.add(s3);
System.out.println(set.size());// 打印集合中对象的数目为2。
Set<泛型> set = new HashSet<泛型>();
其中泛型可以是String类型 Integer类型,也可以自己创建的对象放入其中,这属于最简单的创建Set的实例
2.什么是list?
(1)List的特征是其元素以线性方式存储,集合中可以存放重复对象。
实际上有两种List:一种是基本的ArrayList,其优点在于随机访问元素,另一种是更强大的LinkedList,它并不是为快速随机访问设计的,而是具有一套更通用的方法。
(2)
List:次序是List最重要的特点:它保证维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(这只推 荐LinkedList使用。)一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和移除元素。
ArrayList:由数组实现的List。允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历 ArrayList,而不是用来插入和移除元素。因为那比LinkedList开销要大很多。
LinkedList :在实现中采用链表数据结构。插入和删除速度快,访问速度慢。对顺序访问进行了优化,向List中间插入与删除的开销并不大。随机访问则相对较慢。(使用ArrayList代替)还具有下列方法:addFirst(), addLast(), getFirst(), getLast(), removeFirst() 和 removeLast(), 这些方法 (没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
(3)最基本的两种检索集合中的所有对象的方法:
1、for循环和get()方法:
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
2、使用迭代器(Iterator)
Iterator it = list.iterator();
while (it.hashNext()) {
System.out.println(it.next());
}
3.什么是Map?
1、俗话说学习要学会类比,map对象也一样。书本目录,所有人都知道吧,左边的内容,右边对应的是页码,你只要找到页码所在的页就就可以知道这个页码的内容了。回到map对象也是一个意思,比如:
Map<1,"我">你只要得到Map里面的key1 他对应得到的value值就是我。
Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。
Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
2、Map 的常用方法:
(1)添加,删除操作:
Object put(Object key, Object value): //向集合中加入元素
Object remove(Object key): //删除与KEY相关的元素
void putAll(Map t): //将来自特定映像的所有元素添加给该映像
void clear()://从映像中删除所有映射
(2)查询操作:
Object get(Object key):获得与关键字key相关的值 。Map集合中的键对象不允许重复,也就说,任意两个键对象通过equals()方法比较的结果都是false.但是可以将任意多个键独享映射到同一个值对象上。如不同身份证号的人,却都有一样的名字。
3、Map的功能方法:
(1)put(Object key, Object value)添加一个“值”(想要得东西)和与“值”相关联的“键”(key)(使用它来查找)。
(2)get(Object key)返回与给定“键”相关联的“值”。可以用containsKey()和containsValue()测试Map中是否包含某个“键”或“值”。
4、哈希码值hashcode是“相对唯一”用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。所有Java对象都 能产生散列码,因为hashCode()是定义在基类Object中的方法。
5、
HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显着提高性能。
Map : 维护“键值对”的关联性,使你可以通过“键”查找“值”。
HashMap:Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。
LinkedHashMap: 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。
TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
WeakHashMao :弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。
IdentifyHashMap:使用==代替equals()对“键”作比较的hash map。专为解决特殊问题而设计。
二、Set List Map的区别
1、
List:将以特定次序存储元素。所以取出来的顺序可能和放入顺序不同。
ArrayList / LinkedList / Vector
Set:不能含有重复的元素。
HashSet / TreeSet
Map:HashMap HashTable TreeMap
List,Set,Map将持有对象一律视为Object型别。
List、Set、Map都是接口,不能实例化。
继承自它们的 ArrayList, Vector, HashTable, HashMap是具象class,这些才可被实例化。
vector容器确切知道它所持有的对象隶属什么型别。vector不进行边界检查。
2、总结:
(1)如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用
LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
(2)如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
(3)在除需要排序时使用TreeSet,TreeMap外,都应使用HashSet,HashMap,因为他们 的效率更高。
(4)要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
(5)容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。一旦将对象置入容器内,便损失了该对象的型别信息。
(6)尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。
3、注意:
(1)Set和Collection拥有一模一样的接口。
(2)List,可以通过get()方法来一次取出一个元素。使用数字来选择一堆对象中的一个,get(0)...。(add/get)
(3)一般使用ArrayList。用LinkedList构造堆栈stack、队列queue。
(4)Map用 put(k,v) / get(k),还可以使用containsKey()/containsValue()来检查其中是否含有某个 key/value
HashMap会利用对象的hashCode来快速找到key。
(5)Map中元素,可以将key序列、value序列单独抽取出来。
使用keySet()抽取key序列,将map中的所有keys生成一个Set。
使用values()抽取value序列,将map中的所有values生成一个Collection。
(6)Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。
为什么一个生成Set,一个生成Collection?那是因为,key总是独一无二的,value允许重复。
三、Map中几个概念
1.Map.Entry:
通过查找API文档:
java.util
接口 Map.Entry<K,V>
Map.Entry是一个接口,不能直接实例化
2.Map.entrySet( )
<K,V>> entrySet() //返回此映射中包含的映射关系的视图。
表示映射关系
Map.entrySet( )返回的是一个collection集合,并且,这个collection中的元素是Map.Entry类型。
如:Set<Map.Entry<Integer,String>> set = map.entrySet();
3.Map是Java中的接口,Map.Entry是Map的一个内部接口。java.util.Map.Entry接口主要就是在遍历map的时候用到。Map提供了一些常用方法,如keySet()、entrySet()等方法。
(1)keySet()方法返回值是Map中key值的集合;
(2)entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
(3)Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。它表示Map中的一个实体(一个key-value对)。
(4)Map.Entry接口中有getKey(),getValue方法。所以可以通过Map.Entry的子类对象实现后的方法getKey和getValue来获取关系中的键和值。
四、Java 遍历Map的2种方法(KeySet、EntrySet)
1、keySet()方式
keySet()方法返回值是Map中key值的集合。
map集合本身具备的keySet方法可以将map集合中的键返回到一个Set集合中,在通过Set集合遍历所有的键来获取map集合中所对应的值。
import java.util.*;
public class day6 {
public static void main(String[] args){
Map<String,String> map = new HashMap<String,String>();
map.put("01", "zhangsan");
map.put("02", "lisi");
map.put("03", "wangwu");
//取出map中的所有元素
//先获取map集合的所有键的Set集合
//原理:通过keySet方法获取map中所有的键所在的Set集合,在通过Set的迭代器获取到每一个键
//在对每一个键通过map集合的get方法获取其对应的值即可
Set<String> keySet = map.keySet();
//有了Set集合,就可以获取其迭代器。
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
//有了键可以通过map集合的get方法获取其对应的值。
String value = map.get(key);
System.out.println("key: "+key+"-->value: "+value);//获得key和value值
}
}
}
输出:
key: 01-->value: zhangsan
key: 02-->value: lisi
key: 03-->value: wangwu
在上面的程序中:Set<String> keySet = map.keySet();
Iterator<String> it = keySet.iterator();
相当于: Iterator<String> it = map.keySet().iterator();
2、entrySet()方式
entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
map集合本身具备的entrySet方法可以将map集合中键值对的关系取出来,并返回到一个set集合中,此时可以用迭代器遍历。这个关系的类型就是Map.Entry,其实Entry是map接口中的一个内部接口,并且是static修饰的所以可以用map.来调用,hashmap在实现map接口的同时,在内部也定义了一个内部类来实现了Entry接口,并实现了entry中的方法,所以可以通过Map.Entry的子类对象实现后的方法getKey和getValue来获取关系中的键和值。
import java.util.*;
public class day6 {
public static void main(String[] args){
Map<String,String> map = new HashMap<String,String>();
map.put("01", "zhangsan");
map.put("02", "lisi");
map.put("03", "wangwu");
//方法1:迭代程序---------------------------
//通过entrySet()方法将map集合中的映射关系取出(这个关系的类型就是Map.Entry类型)
//通过Map转成Set就可以迭代
//该方法将键和值的映射关系作为对象存储到了Set集合中
//因为转换成了Set,所以可以用Set的引用承接
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//将关系集合entrySet进行迭代,存放到迭代器中
Iterator<Map.Entry<String, String>> it2 = entrySet.iterator();
while(it2.hasNext()){
//获取Map.Entry关系对象me
Map.Entry<String, String> me = it2.next();
//通过关系对象获取key
String key2 = me.getKey();
//通过关系对象获取value
String value2 = me.getValue();
System.out.println("key: "+key2+"-->value: "+value2);
}
//方法2:其他方法---------------------------
for(Map.Entry<String, String> c : map.entrySet()){
System.out.println("key: "+c.getKey()+"-->value: "+c.getValue());
}
}
}
输出:
key: 01-->value: zhangsan
key: 02-->value: lisi
key: 03-->value: wangwu
总结:同时遍历Map的键与值:先用entrySet方法转换成Set集合,遍历Set时,在循环内部将it.next()转换成Map.Entry形式,利用Map.Entry的getKey和getValue方法,得到键和值。
3.两种方式比较
虽然使用keyset及entryset来进行遍历能取得相同的结果
但两者的遍历速度是有差别的。
keySet():迭代后只能通过get()取key
entrySet():迭代后可以e.getKey(),e.getValue()取key和value。返回的是Entry接口
说明:keySet()的速度比entrySet()慢了很多,也就是keySet方式遍历Map的性能不如entrySet性能好
为了提高性能,以后多考虑用entrySet()方式来进行遍历。
4.补充 values()方法
values()方法返回值是Map中value值的集合。
还有一种遍历方法是,单纯的遍历value值,Map有一个values方法,返回的是value的Collection集合。通过遍历collection也可以遍历value。
import java.util.*;
public class day6 {
public static void main(String[] args){
Map<String,String> map = new HashMap<String,String>();
map.put(01, "zhangsan");
map.put(02, "lisi");
map.put(03, "wangwu");
showValue(map);
}
public static void showValue(Map<Integer, String> map) {
Collection<String> values = map.values();
Iterator<String> it = values.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
输出:
zhangsan
lisi
wangwu
五、去掉注释,完整的遍历Map的2种方法
import java.util.*;
public class day6 {
public static void main(String[] args){
Map<String,String> map = new HashMap<String,String>();
map.put("01", "zhangsan");
map.put("02", "lisi");
map.put("03", "wangwu");
//1. keySet()方式---------------------------
Set<String> keySet = map.keySet();
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
String value = map.get(key);
System.out.println("key: "+key+"-->value: "+value);
}
//2. entrySet()方式--------------------------
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it2 = entrySet.iterator();
while(it2.hasNext()){
Map.Entry<String, String> me = it2.next();
String key2 = me.getKey();
String value2 = me.getValue();
System.out.println("key: "+key2+"-->value: "+value2);
}
//方法2.中for循环形式---------------------------
for(Map.Entry<String, String> c : map.entrySet()){
System.out.println("key: "+c.getKey()+"-->value: "+c.getValue());
}
}
}
其中:程序中:Set<String> keySet = map.keySet();
Iterator<String> it = keySet.iterator();
相当于: Iterator<String> it = map.keySet().iterator();
本篇博文是小白我在大神的肩膀上,吸收整理出来的。衷心感谢大神们的无私奉献、厚薄积发的精神,这种品质给我们小白在技术上的成长带来了很大的帮助。