Java容器大全

Java容器大全

Java容器大全一、集合框架二、Iterator题外话1. C++中的Reference与Pointer2. 内存分析三、Array、Arrays与ArrayList四、HashMap1. 概念2. 用法五、Set、List与Array之间的互转1. Set与List互转2. Array与List互转3. Array与Set互转一、集合框架Java集合框架(java.util包)主要包括两种类型的容器:一种是集合Collection,存储一个元素集合;另一种是图Map,存储键值对映射。

所有的集合框架都包含:接口、实现(类)、算法。任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换。

接口

Collection:最基本的集合接口,代表一组Object

List:有序,add()方法添加

Set:不重复,add()方法添加

SortedSet:有序不重复

Map:键值对,put()方法添加

Map.Entry:Map中的一个元素,Map的内部类

SortedMap:key有序

Enumeration:枚举

实现类

分为具体类(直接拿来用)和抽象类(提供了接口的部分实现)。

LinkedList:允许有null,用于创建链表

ArrayList:可变大小的数组

HashSet:允许包含最多一个null,只存储对象

LinkedHashSet:具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现

HashMap:散列表,最多允许一条键为null的记录

LinkedHashMap:使用元素自然顺序进行排列

Vector:与ArrayList类似,是同步的

Stack:是Vector的一个子类,栈

Dictionary:抽象类,存储键值对

Hashtable:Dictionary类的子类,是同步的,不能存null

Properties:继承于Hashtable,表示一个持久的属性值,键值都是String

BitSet:存储位值得数组

方法

代码语言:javascript复制boolean add(Object o) //添加对象到集合

boolean remove(Object o) //删除指定的对象

int size() //返回当前集合中元素的数量

boolean contains(Object o) //查找集合中是否有指定的对象

boolean isEmpty() //判断集合是否为空

Iterator iterator() //返回一个迭代器

boolean containsAll(Collection c)//查找集合中是否有集合c中的元素

boolean addAll(Collection c) //将集合c中所有的元素添加给该集合

void clear() //删除集合中所有元素

void removeAll(Collection c) //从集合中删除c集合中也有的元素

void retainAll(Collection c) //从集合中删除集合c中不包含的元素二、IteratorCollection是个接口,你的类继承这个接口必须实现这个接口里面的所有函数,其中就包括Iterator< E> iterator()这个函数。

迭代器是一种设计模式,是一个标准化遍历各类容器里面的所有对象的方法类,可以遍历并选择序列中的对象而不用关心底层结构。Java中的Iterator功能较为简单,只能单项移动。(ListIterator可以双向遍历,更为灵活)

接口定义:

代码语言:javascript复制public interface Iterator {

boolean hasNext();

Object next();

void remove();

}

//用法,以List为例

Iterator iter = list.iterator();题外话1. C++中的Reference与Pointer代码语言:javascript复制int i = 1;

int *pi = &i;//i是一个指针类型的对象,并且也是一个“指向int整型的指针”,它的初始化值为对象i的地址

int &ri = i; //i是一个引用类型的对象,并且也是一个指向整型的引用,它指向的是i

//赋初值

*pi = 1;//后续可以指向其他不同的对象,可以为null

ri = 1;//后续不可以改变,类似于常量指针,有意义必须要指向一个对象二者的区别(参考《More Effective C++》)

1.没有null reference;

2.reference必须有初值;

3.使用reference要比使用指针效率高。因为reference不需要测试其有效性;

4.指针可以重新赋值,而reference总是指向它最初获得的对象。

Java中的Reference

Java中的引用可以随意赋值,并且可以为null,可以理解成一个披着C++中reference的pointer。实际上,Java中的reference就是一个地址,地位等同于C++中的point。

2. 内存分析栈

1.描述的是方法执行的内存模型,每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等);

2.JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等);

3.栈属于线程私有,不能实现线程间的共享;

4.栈的存储特性是“先进后出”,由系统自动分配,速度快,是一片连续的内存空间。堆

1.用于存储创建好的对象和数组;

2.JVM只有一个堆,被所有线程共享;

3.堆是一个不连续的内存空间,分配灵活,速度慢。方法区(静态区)

1.JVM只有一个方法区,实际上也是堆,被所有线程共享,存放类、常量相关的信息;

2.用来存放程序中永远不变或唯一的内容(类信息、静态变量、字符串常量等)。

三、Array、Arrays与ArrayListArray是对象数组的类(对象的reference)与基本类型数组非常类似,大小固定,可以存储基本数据类型和对象,Array还可以作为函数返回值。

Arrays是对数组的一系列操作,是工具类java.util.Arrays。

ArrayList是一个容器(一个个reference指向Object),只能存储对象,不能存储原生数据类型(上一篇博客中讨论过,如int)。java.util.ArrayList< E>长度是动态的,可以存储任意多个对象(泛型固定的类型),牺牲了效率,可以视为Array的二次封装。

分析:当能确定长度并且数据类型一致的时候就可以用数组,其他时候使用ArrayList。

List是一个接口,而ArrayList是其实现类,List无法被直接构造(new),但是可以通过List list = new ArrayList()来构造。

四、HashMap1. 概念HashMap继承于AbstractMap,基于散列表,实现了Map、Cloneable、java.io.Serializable接口。存储的内容是键值对映射,利用拉链法实现。其实现是不同步的,即非线程安全,key和value都可以是null。此外,HashMap中的映射不是有序的。

影响HashMap的实例有两个参数:初始容量和加载因子。

通常默认加载因子是0.75,当哈希表中的条目超过了加载因子与初始容量的乘积时,就要对该哈希表进行rehash操作,重建内部数据结构,使哈希表大约有两倍的桶数。

TreeMap基于红黑树实现的,内部元素是按需排列的。

2. 用法构造函数:

代码语言:javascript复制// 默认构造函数。

HashMap()

// 指定“容量大小”的构造函数

HashMap(int capacity)

// 指定“容量大小”和“加载因子”的构造函数

HashMap(int capacity, float loadFactor)

// 包含“子Map”的构造函数

HashMap(Map map)API:

代码语言:javascript复制void clear() //清空表

Object clone()

boolean containsKey(Object key) //判断是否包含键为key的键值对

boolean containsValue(Object value) //判断是否包含值为value的键值对

V get(Object key) //获取key对应的value

boolean isEmpty() //判断是否为空

V put(K key, V value) //添加一个映射

void putAll(Map map)//将map所有的元素加入到表中

V remove(Object key) //删除键为key的元素

int size() //获得表大小

Set> entrySet() //返回所有Entry的集合

Set keySet() //返回所有key的集合

Collection values() //返回所有value的集合遍历方式:

代码语言:javascript复制//遍历键值对

Iterator iter = hashMap.entrySet().iterator();

while (iterator.hasNext()){

Map.Entry entry = (Map.Entry) iter.next();

String key = (String) entry.getKey();

Integer value = (Integer) entry.getValue();

}

//遍历键

Iterator iter = hashMap.keySet().iterator();

key = (String) iter.next();

value = (Integer)hashMap.get(key);

//遍历值

Collection c = hashMap.values();

Iterator iter = c.iterator();

value = (Integer) iter.next();HashMap与TreeMap的对比

五、Set、List与Array之间的互转1. Set与List互转因为List和Set都实现了Collection接口,且addAll(Collection c);方法,因此可以采用addAll()方法将List和Set互相转换;另外,List和Set也提供了Collection c作为参数的构造函数,因此通常采用构造函数的形式完成互相转化。

代码语言:javascript复制//List转Set

List list = new ArrayList<>();

Set set = new HashSet<>(list);

//Set转List

Set set = new HashSet<>();

List list_1 = new ArrayList<>(set);注意:这里list与set相互独立,改变其中一个不会影响另一个。

2. Array与List互转注意引用的情况。

代码语言:javascript复制//Array转List

String[] s = new String[]{"A", "B", "C", "D","E"};

List list = Arrays.asList(s);//s改变会影响list

List list = Arrays.asList(Arrays.copyOf(s, s.length));//s改变不会影响list

//List转Array

String[] s1 = list.toArray(new String[list.size()]);//new String[len]是指定返回数组的类型

String[] s1 = (String[]) list.toArray();//或者强转3. Array与Set互转由1、2可以推出:

代码语言:javascript复制//array转set

s = new String[]{"A", "B", "C", "D","E"};

Set set = new HashSet<>(Arrays.asList(s));

//set转array

String[] s1= set.toArray(new String[0]);

String[] s1= (String[]) set.toArray();总结:上述列出的互相转换离不开Arrays.asList()和Collection.toArray()两个重要的方法。需要注意的是asList()函数的参数必须是对象,如果是int[],必须先转换成Integer[]。如果强行转换的话,需要用到jdk 1.8中的stream。

代码语言:javascript复制List list =

int[] i =