您的位置:首页 > 职场人生

黑马程序员java自学总结之--集合

2014-12-14 16:25 417 查看
Java培训、Android培训、iOS培训、.Net培训、期待与您交流!

什么是集合

一般地,我们把研究对象统称为元素;把一些元素组成的总体叫做集合,也简称集合元素的特征,java中的集合是用来存放对象的容器,其中数组可以放对象和基本数据类型。

(1)确定性:设A是一个给定的集合,x是某一个具体对象,则或者是A的元素,或者不是A的元素,两种情况必有一种且只有一种成立.

(2)互异性:一个给定集合中的元素,指属于这个集合的互不相同的个体(对象),因此,同一集合中不应重复出现同一元素.

(3)无序性:一般不考虑元素之间的顺序,但在表示数列之类的特殊集合时,通常按照习惯的由小到大的数轴顺序书写

java中的集合体系



java.lang

接口 Iterable<T>

实现这个接口允许对象成为 "foreach" 语句的目标。

collection接口

Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如Set 和List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。

boolean add(E e)

确保此 collection 包含指定的元素(可选操作)。

boolean addAll(Collection<? extendsE> c)

将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。

void clear()

移除此 collection 中的所有元素(可选操作)。

boolean contains(Object o)

如果此 collection 包含指定的元素,则返回 true。

boolean containsAll(Collection<?> c)

如果此 collection 包含指定 collection 中的所有元素,则返回 true。

boolean equals(Object o)

比较此 collection 与指定对象是否相等。

int hashCode()

返回此 collection 的哈希码值。

boolean isEmpty()

如果此 collection 不包含元素,则返回 true。

Iterator<E> iterator()

返回在此 collection 的元素上进行迭代的迭代器。

boolean remove(Object o)

从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。

boolean removeAll(Collection<?> c)

移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。

boolean retainAll(Collection<?> c)

仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。

int size()

返回此 collection 中的元素数。

Object[] toArray()

返回包含此 collection 中所有元素的数组。

<T> T[]

toArray(T[] a)

返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

类 Collections

在学习数组的时候有一个操作数组的工具类Arrays,这个类中封装了一系列的静态方法对数组进行操作,可以便利我们的的开发,同样,在对集合中Collections类中也封装了一系列的对集合操作的方法。具体的方法,我们可以通过查阅API文档来查看。

list接口

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

与 set 不同,列表通常允许重复的元素。更确切地讲,列表通常允许满足 e1.equals(e2) 的元素对 e1 和 e2,并且如果列表本身允许 null 元素的话,通常它们允许多个 null 元素。难免有人希望通过在用户尝试插入重复元素时抛出运行时异常的方法来禁止重复的列表,但我们希望这种用法越少越好。

List 接口在 iterator、add、remove、equals 和hashCode 方法的协定上加了一些其他约定,超过了Collection 接口中指定的约定。为方便起见,这里也包括了其他继承方法的声明。

List 接口提供了 4 种对列表元素进行定位(索引)访问方法。列表(像 Java 数组一样)是基于 0 的。注意,这些操作可能在和某些实现(例如LinkedList 类)的索引值成比例的时间内执行。因此,如果调用者不知道实现,那么在列表元素上迭代通常优于用索引遍历列表。

List 接口提供了特殊的迭代器,称为 ListIterator,除了允许 Iterator 接口提供的正常操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器。

List 接口提供了两种搜索指定对象的方法。从性能的观点来看,应该小心使用这些方法。在很多实现中,它们将执行高开销的线性搜索。

List 接口提供了两种在列表的任意位置高效插入和移除多个元素的方法。

boolean add(E e)

向列表的尾部添加指定的元素(可选操作)。

void add(int index,E element)

在列表的指定位置插入指定元素(可选操作)。

boolean addAll(Collection<? extendsE> c)

添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。

boolean addAll(int index,Collection<? extends E> c)

将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。

void clear()

从列表中移除所有元素(可选操作)。

boolean contains(Object o)

如果列表包含指定的元素,则返回 true。

boolean containsAll(Collection<?> c)

如果列表包含指定 collection 的所有元素,则返回 true。

boolean equals(Object o)

比较指定的对象与列表是否相等。

E get(int index)

返回列表中指定位置的元素。

int hashCode()

返回列表的哈希码值。

int indexOf(Object o)

返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

boolean isEmpty()

如果列表不包含元素,则返回 true。

Iterator<E> iterator()

返回按适当顺序在列表的元素上进行迭代的迭代器。

int lastIndexOf(Object o)

返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。

ListIterator<E> listIterator()

返回此列表元素的列表迭代器(按适当顺序)。

ListIterator<E> listIterator(int index)

返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

E remove(int index)

移除列表中指定位置的元素(可选操作)。

boolean remove(Object o)

从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。

boolean removeAll(Collection<?> c)

从列表中移除指定 collection 中包含的其所有元素(可选操作)。

boolean retainAll(Collection<?> c)

仅在列表中保留指定 collection 中所包含的元素(可选操作)。

E set(int index,E element)

用指定元素替换列表中指定位置的元素(可选操作)。

int size()

返回列表中的元素数。

List<E> subList(int fromIndex, int toIndex)

返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

Object[] toArray()

返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。

<T> T[]

toArray(T[] a)

返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。

set接口

一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的set 抽象。

在所有构造方法以及 add、equals 和 hashCode 方法的协定上,Set 接口还加入了其他规定,这些规定超出了从Collection 接口所继承的内容。出于方便考虑,它还包括了其他继承方法的声明(这些声明的规范已经专门针对Set 接口进行了修改,但是没有包含任何其他的规定)。

对这些构造方法的其他规定是(不要奇怪),所有构造方法必须创建一个不包含重复元素的 set(正如上面所定义的)。

注:如果将可变对象用作 set 元素,那么必须极其小心。如果对象是 set 中某个元素,以一种影响 equals 比较的方式改变对象的值,那么 set 的行为就是不确定的。此项禁止的一个特殊情况是不允许某个 set 包含其自身作为元素。

某些 set 实现对其所包含的元素有所限制。例如,某些实现禁止 null 元素,而某些则对其元素的类型所有限制。试图添加不合格的元素会抛出未经检查的异常,通常是NullPointerException 或ClassCastException。试图查询不合格的元素是否存在可能会抛出异常,也可能简单地返回 false;某些实现会采用前一种行为,而某些则采用后者。概括地说,试图对不合格元素执行操作时,如果完成该操作后不会导致在 set 中插入不合格的元素,则该操作可能抛出一个异常,也可能成功,这取决于实现的选择。此接口的规范中将这样的异常标记为“可选”。

boolean add(E e)

如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。

boolean addAll(Collection<? extendsE> c)

如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中(可选操作)。

void clear()

移除此 set 中的所有元素(可选操作)。

boolean contains(Object o)

如果 set 包含指定的元素,则返回 true。

boolean containsAll(Collection<?> c)

如果此 set 包含指定 collection 的所有元素,则返回 true。

boolean equals(Object o)

比较指定对象与此 set 的相等性。

int hashCode()

返回 set 的哈希码值。

boolean isEmpty()

如果 set 不包含元素,则返回 true。

Iterator<E> iterator()

返回在此 set 中的元素上进行迭代的迭代器。

boolean remove(Object o)

如果 set 中存在指定的元素,则将其移除(可选操作)。

boolean removeAll(Collection<?> c)

移除 set 中那些包含在指定 collection 中的元素(可选操作)。

boolean retainAll(Collection<?> c)

仅保留 set 中那些包含在指定 collection 中的元素(可选操作)。

int size()

返回 set 中的元素数(其容量)。

Object[] toArray()

返回一个包含 set 中所有元素的数组。

<T> T[]

toArray(T[] a)

返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。

Map接口

将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

此接口取代 Dictionary 类,后者完全是一个抽象类,而不是一个接口。

Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序 定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如TreeMap 类;另一些映射实现则不保证顺序,如HashMap 类。

static interface Map.Entry<K,V>

映射项(键-值对)。

方法摘要

void clear()

从此映射中移除所有映射关系(可选操作)。

boolean containsKey(Object key)

如果此映射包含指定键的映射关系,则返回 true。

boolean containsValue(Object value)

如果此映射将一个或多个键映射到指定值,则返回 true。

Set<Map.Entry<K,V>> entrySet()

返回此映射中包含的映射关系的 Set 视图。

boolean equals(Object o)

比较指定的对象与此映射是否相等。

V get(Object key)

返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

int hashCode()

返回此映射的哈希码值。

boolean isEmpty()

如果此映射未包含键-值映射关系,则返回 true。

Set<K> keySet()

返回此映射中包含的键的 Set 视图。

V put(K key,V value)

将指定的值与此映射中的指定键关联(可选操作)。

void putAll(Map<? extendsK,? extendsV> m)

从指定映射中将所有映射关系复制到此映射中(可选操作)。

V remove(Object key)

如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

int size()

返回此映射中的键-值映射关系数。

Collection<V> values()

返回此映射中包含的值的 Collection 视图。

java.util

类 ArrayList<E>

java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractList<E>

继承者 java.util.ArrayList<E>

package com.ccus.collection;

import java.util.ArrayList;
import java.util.Collection;

public class ArraylistDemo1 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
list2.add(8);
list2.add(9);
//增
list1.add(1);
list1.add(2);//增加一个元素
list1.addAll(list2);//在集合末尾增加一个集合
//        System.out.println(list1);
//        //删
//        list1.remove(1);//删除一个集合
//        System.out.println(list1);
//        list1.removeAll(list2);//删除集合中的一个子集合
//        System.out.println(list1);
//        list1.clear();//清空一个集合
//        System.out.println(list1);
//改
list1.set(1,100);
System.out.println(list1);
//查
System.out.println(list1.contains(100));
System.out.println(list1.containsAll(list2));
System.out.println(list1.get(1));
System.out.println(list1.indexOf(100));
System.out.println(list1.lastIndexOf(8));

}
}

两种方法来遍历一个list

由于list实现了iterable接口,所以可以使用foreach循环遍历,还可以使用迭代器遍历

package com.ccus.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Traverse {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(5);
list.add(0);
Iterator i = list.iterator();
while(i.hasNext())
{
System.out.println(i.next());
}
for(Object o:list)
{
System.out.println(o);
}
}
}


java.util

类 LinkedList<E>

java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractList<E>

继承者 java.util.AbstractSequentialList<E>

继承者 java.util.LinkedList<E>

List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾get、remove 和insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。

此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。

所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。

import java.util.*;

/*
LinkedList:特有方法:
addFirst();
addLast();

getFirst();
getLast();
获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException

removeFirst();
removeLast();
获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException

在JDK1.6出现了替代方法。

offerFirst();
offerLast();

peekFirst();
peekLast();
获取元素,但不删除元素。如果集合中没有元素,会返回null。

pollFirst();
pollLast();
获取元素,但是元素被删除。如果集合中没有元素,会返回null。

*/

class LinkedListDemo
{
public static void main(String[] args)
{
LinkedList link = new LinkedList();

link.addLast("java01");
link.addLast("java02");
link.addLast("java03");
link.addLast("java04");

//sop(link);
//        sop(link.getFirst());
//        sop(link.getFirst());
//sop(link.getLast());
//sop(link.removeFirst());
//sop(link.removeFirst());

//sop("size="+link.size());

while(!link.isEmpty())
{
sop(link.removeLast());
}

}

public static void sop(Object obj)
{
System.out.println(obj);
}
}
java.util

类 HashSet<E>

java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractSet<E>

继承者 java.util.HashSet<E>

底层数据结构是哈希表。是线程不安全的。不同步。

HashSet是如何保证元素唯一性的呢?

是通过元素的两个方法,hashCode和equals来完成。

如果元素的HashCode值相同,才会判断equals是否为true。

如果元素的hashcode值不同,不会调用equals。

注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。

package com.ccus.collection;

import java.util.*;

public class HashSetDemo {
public static void main(String[] args) {
HashSet hs = new HashSet();
Person p1 = new Person("小叶",20);
String name = "小叶";
String name1 = "小叶";
System.out.println(name.hashCode());
System.out.println(name1.hashCode());
hs.add(new Person("小叶",20));
hs.add(new Person("小明",20));
hs.add(new Person("小李",20));
System.out.println(hs.add(new Person("小叶",20)));
System.out.println(hs);
//hs.remove(p1);
System.out.println(hs);
Iterator i = hs.iterator();
while(i.hasNext())
{
System.out.println((Person)i.next());
}
//hs.add(p4);
}

}
class Person
{
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
if(this.name == p.name && this.age == p.age)
{
return true;
}
else
return false;
};
public int hashCode() {

return name.hashCode();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
private String name;
private int age;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}


java.util

类 Vector<E>

java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractList<E>

继承者 java.util.Vector<E>

/*
枚举就是Vector特有的取出方式。
发现枚举和迭代器很像。
其实枚举和迭代是一样的。

因为枚举的名称以及方法的名称都过长。
所以被迭代器取代了。
枚举郁郁而终了。

*/
class VectorDemo
{
public static void main(String[] args)
{
Vector v = new Vector();

v.add("java01");
v.add("java02");
v.add("java03");
v.add("java04");

Enumeration en = v.elements();

while(en.hasMoreElements())
{
System.out.println(en.nextElement());
}
}
}
java.util

类 TreeSet<E>

java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractSet<E>

继承者 java.util.TreeSet<E>

可以对Set集合中的元素进行排序。

底层数据结构是二叉树。

保证元素唯一性的依据:

compareTo方法return 0.

TreeSet排序的第一种方式:让元素自身具备比较性。

元素需要实现Comparable接口,覆盖compareTo方法。

也种方式也成为元素的自然顺序,或者叫做默认顺序。

TreeSet的第二种排序方式。

当元素自身不具备比较性时,或者具备的比较性不是所需要的。

这时就需要让集合自身具备比较性。

在集合初始化时,就有了比较方式。

package com.ccus.collection;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo2 {

/**
* @param args
* 按字符串的长度排序
*/
public static void main(String[] args) {
String s1 = "efwefwe";
String s2 = "wer";
String s3 = "e";
String s4 = "gfsdgrsghrgesr";
TreeSet ts = new TreeSet(new MyCompartor());
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
Iterator i = ts.iterator();
while(i.hasNext())
{
System.out.println(i.next());
}
}

}

class MyCompartor implements Comparator
{

@Override
public int compare(Object o1, Object o2) {
if(!(o1 instanceof String) || !(o2 instanceof String))
{
throw new RuntimeException("数据类型错误");
}
String s1 = (String)o1;
String s2 = (String)o2;
if(s1.length() > s2.length())
return 1;
else if(s1.length() == s2.length())
return 0;
else
return -1;
}

}


java.util

接口 Map<K,V>

类型参数:

K - 此映射所维护的键的类型

V - 映射值的类型

将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

此接口取代 Dictionary 类,后者完全是一个抽象类,而不是一个接口。

Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序 定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如TreeMap 类;另一些映射实现则不保证顺序,如HashMap 类。

package com.ccus.collection;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo {

/**
* @param args
*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("01", "小叶");
map.put("02", "小立");
map.put("o3", "胜多负少");
map.put("04", "小厘米");
System.out.println(map);
map.remove("01");
System.out.println(map);
Collection coll = map.values();
System.out.println(coll);
Set set = map.keySet();
System.out.println(set);
Set set1 = map.entrySet();
System.out.println(set1);
}

}


两种方式来取map中的元素。

public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1", "01");
map.put("2", "02");
map.put("3", "03");
map.put("4", "04");
Set<String> set1 = map.keySet();
Iterator<String> i1 = set1.iterator();
while(i1.hasNext())
{
String key1 = i1.next();
String value1 = map.get(key1);
System.out.println(key1+":"+value1);
}
System.out.println("------------------");
Set<Map.Entry<String,String>> set2 = map.entrySet();
Iterator<Map.Entry<String,String>> i2 = set2.iterator();
while(i2.hasNext())
{
Map.Entry<String, String> i3 = i2.next();
String key2 = i3.getKey();
String value2 = i3.getValue();
System.out.println(key2+":"+value2);
}
}


练习:

"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

希望打印结果:a(1)c(2).....

package com.ccus.collection;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapTest {
public static void main(String[] args) {
System.out.println(charCount("fsfsoejfiaofojgfhh"));
}
public static String charCount(String str)
{
char[] list = str.toCharArray();
TreeMap<Character,Integer> map = new TreeMap<Character,Integer>();
int count = 0;

for(char c:list)
{
Integer value = map.get(c);
if(value != null)
{
count = value;
}
count++;
map.put(c, count);
count = 0;
if(value == null)
{
map.put(c, 1);
}else
{
value++;
map.put(c, value);
}

}
StringBuilder sb = new StringBuilder();

Set<Map.Entry<Character,Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<Character,Integer>>  it = entrySet.iterator();

while(it.hasNext())
{
Map.Entry<Character,Integer> me = it.next();
Character ch = me.getKey();
Integer value = me.getValue();
sb.append(ch+"("+value+")");
}
return sb.toString();
}
}


总结

  如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。

  如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。

  要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。

  尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

同步性

Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并 不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带 来的不必要的性能开销。

数据增长

从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目 超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最 后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初 始化大小来避免不必要的资源开销。

使用模式

在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用 O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除 元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?

这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他 的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢 -O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也 会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。

最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组 (Array)避免了同步、额外的方法调用和不必要的重新分配空间的操作。

相互区别

Vector和ArrayList

1,vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用

arraylist效率比较高。

2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度

的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。

3,如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而

如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用linklist,因为它移动一个指定位置的数据

所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。

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

arraylist和linkedlist

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。

2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数 据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

HashMap与TreeMap

1、HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。

HashMap中元素的排列顺序是不固定的)。

2、 HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该 使用TreeMap(HashMap中元素的排列顺序是不固定的)。集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。

3、在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现。  这个TreeMap没有调优选项,因为该树总处于平衡状态。

结过研究,在原作者的基础上我还发现了一点,二树map一样,但顺序不一样,导致hashCode()不一样。

同样做测试:

在hashMap中,同样的值的map,顺序不同,equals时,false;

而在treeMap中,同样的值的map,顺序不同,equals时,true,说明,treeMap在equals()时是整理了顺序了的。

hashtable与hashmap

一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现

二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的

三.值:只有HashMap可以让你将空值作为一个表的条目的key或value
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: