集合和数组的区别
**1、**数组长度不变且无法保证映射关系
**2、**数组元素可以保存基本类型,对象,同种类型;集合只能保存引用类型(对象),不同类型
集合层级
- 集合主要由俩个接口Collection和Map派生
- Collection派生出三个接口:List、set、Queue(队列在java5添加)
而Collection常见的接口方法:如下
List 和 Set 分别的实现类
(1)List 实现类
List集合代表一个有序可重复的集合,集合中每一个元素对应一个顺序索引。默认按元素的添加方式设置索引,即通过指定索引下标设置索引(来访问指定位置的集合元素):实现List接口主要有:ArrayList、LinkedList、Vector(可以用copyWriteArrayList代替安全集合)、Stact(未用过)。
ArrayList:
动态数组,初始长度是10。允许任何符合规则的元素插入,包括null。随着容器中的元素不断增加,容器的大小也会不断增加。在每次容器增加元 素的同时进行容量的检测,当快溢出时,就会进行扩容。如果明确知道插入元素多少,最好指定它的容量大小,避免进行过多的扩容浪费时间, 效率;(ArrayList擅长随机访问,同时ArrayList是非同步的)
LinkedList:
内部是以连表的形式保存集合元素,所以在查询方便是慢的,在增删有较好的性能和ArrayList恰巧相反;可以根据索引访问集合,同时也实现了Deque接口,可以当做双端队列使用(意思就是说,可以当做栈使用,也可以当做队列使用)
Vector:
与ArrayList相似,动态数组,但Vector是同步的,在线程安全方面同的比较多
Stack:
继承自Vector,实现一个后进先出的堆栈(未了解)
(2)、Set实现类
HashSet:
是一个没有重复元素的集合。由hashMap实现,不能保证元素的顺序(插入和输出的顺序不一定一致)—(但内部位置hashCode所以相应的位置 也是固定的,存储对象后方便比较一定要重写对象的equals和hashcode),允许null元素(只能有一个)。HashSet是非同步的,如果多个线程 访问一个hashset,其中一个修改了该set,那么必须保持外部同步。 hashset用Hash算法用来存储集合元素,因此具有更好的存取和查找性能;
LinkedHashSet:
继承hashSet,底层是基于LinkedHashMap实现的。有序,非同步。可以通过元素的添加顺序访问集合元素
TreeSet:
有序集合,其底层基于TreeMap实现 ,可以确保元素处于排序状态,支持俩种排序一个是:自然排序,一个是定制排序。通过compare 或者 compareTo判断函数是否相等,通过判断元素id,相同不会被加入集合
(3)、Map实现类
简介:Map接口采用键值对,key-value 存储方式。key值不允许重复,可以视为null。如果有同样的key,则添加put后会 覆盖之前的value;
Map常见方法(来源于API)如下:
HashMap和HashTable(目前基本不用了):类似与ArrayList 和vector
区别:HashMap线程不安全,Hashtable线程安全
HashMap可以使用null值最为key或value;Hashtable不允许使用null值作为key和value
Hashmap的工作原理:
HashMap基于hashing原理,通过put()和get()方法存储和获取对象。当我们将键值对传递给put()方法时,它调用建对象的hashCode()方法来计算hashCode值,然后找到bucket位置来储存值对象。当获取对象时,通过建对象的equals()方法找到正确的键值对,然后返回对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会存储在链表的下一个节点中
LinkedHashMap:
使用双向链表维护key_value的次序(只考虑key的次序就好了),该链表负责维护Map的迭代顺序,与插入顺序一致,因此性能比HashMap低,但是在迭代访问Map中的全部元素有着较好性能
Propertise:
是hashtable的一个子类,它相当与一个key,value都是String类型的Map,主要用于读取配置文件。
TreeMap:
是SortedMap的实现类,是一个红黑树数据结构,每一个key_value对作为一个红黑树的一个节点。TreeMap储存key_value对时,需要根据key对节 点进行排序。TreeMap也有俩种排序方式。
*自然排序:所有的类实现comparable接口,所有的key是同一个类的对象。否则会抛出ClassCastException
*定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序
各Map实现类的性能分析
♦ HashMap通常比Hashtable(古老的线程安全的集合)要快
♦ TreeMap通常比HashMap、Hashtable要慢,因为TreeMap底层采用红黑树来管理key-value。
♦ LinkedHashMap比HashMap慢一点,因为它需要维护链表来爆出key-value的插入顺序
1、map中的hashMap结构和put过程
(4)、Iterator 与 ListIterator详解
一,Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口如下:
hasNext():如果迭代器中还有元素,则返回true。
next():返回迭代器中的下一个元素
remove():删除迭代器新返回的元素。
二、ListIterator是一个功能更加强大的, 它继承于Iterator接口,只能用于各种List类型的访问。可以通过调用listIterator()方法产生一个指向List开始处的 ListIterator(除了上面的接口,下面的方法同样使用)
**add():**在迭代器中新添加元素
**set():**在迭代器中修改元素
**hasPrevious():**向前遍历如果迭代器中还有元素,则返回true。
**previous():**返回迭代器中的下一个元素
nextIndex(): 当前元素后一个元素的索引
**previousIndex():**当前元素前一个元素的索引
注意:
(1)Iterator只能单向移动。
(2)Iterator.remove()是唯一安全的方式来在迭代过程中修改集合;如果在迭代过程中以任何其它的方式修改了基本集合将会产生未知的行为。而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个异常
2、如何遍历map
方法一 在for-each循环中使用entries来遍历(集合不能为空)
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
方法二 在for-each循环中遍历keys或values,而不是用entrySet
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
//遍历map中的键
for (Integer key : map.keySet()) {
System.out.println("Key = " + key);
}
//遍历map中的值
for (Integer value : map.values()) {
System.out.println("Value = " + value);
}
方法三 使用Iterator遍历
使用泛型
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<Integer, Integer> entry = entries.next();
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
不使用泛型:
Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
Integer key = (Integer)entry.getKey();
Integer value = (Integer)entry.getValue();
System.out.println("Key = " + key + ", Value = " + value);
}
/**该种方式看起 == 来冗余却有其优点所在。首先,在老版本java中这是惟一遍历map的方式。另一个好处是,你可以在遍历时调用iterator.remove()来删除entries,另两个方法则不能。根据javadoc的说明,如果在for-each遍历中尝试使用此方法,结果是不可预测的。
**/
方法四、通过键找值遍历(效率低)
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
Integer value = map.get(key);
System.out.println("Key = " + key + ", Value = " + value);
}
总结
如果仅需要键(keys)或值(values)使用方法二。如果你使用的语言版本低于java 5,或是打算在遍历时删除entries,必须使用方法三。否则使用方法一(键值都要)。