Java容器大全

2022-10-25 15:35:53 浏览数 (1)

Java容器大全

  • 一、集合框架
  • 二、Iterator
  • 题外话
    • 1. C 中的Reference与Pointer
    • 2. 内存分析
  • 三、Array、Arrays与ArrayList
  • 四、HashMap
    • 1. 概念
    • 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中不包含的元素

二、Iterator

Collection是个接口,你的类继承这个接口必须实现这个接口里面的所有函数,其中就包括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与ArrayList

Array是对象数组的类(对象的reference)与基本类型数组非常类似,大小固定,可以存储基本数据类型和对象,Array还可以作为函数返回值。 Arrays是对数组的一系列操作,是工具类java.util.Arrays。 ArrayList是一个容器(一个个reference指向Object),只能存储对象,不能存储原生数据类型(上一篇博客中讨论过,如int)。java.util.ArrayList< E>长度是动态的,可以存储任意多个对象(泛型固定的类型),牺牲了效率,可以视为Array的二次封装。

分析:当能确定长度并且数据类型一致的时候就可以用数组,其他时候使用ArrayList。 List是一个接口,而ArrayList是其实现类,List无法被直接构造(new),但是可以通过List list = new ArrayList()来构造。

四、HashMap

1. 概念

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<? extends K, ? extends V> 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<? extends K, ? extends V> map)//将map所有的元素加入到表中
V                   remove(Object key)                       //删除键为key的元素
int                 size()                                   //获得表大小

Set<Entry<K, V>>    entrySet()                               //返回所有Entry的集合
Set<K>              keySet()                                 //返回所有key的集合
Collection<V>       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<? extends E> c);方法,因此可以采用addAll()方法将List和Set互相转换;另外,List和Set也提供了Collection<? extends E> c作为参数的构造函数,因此通常采用构造函数的形式完成互相转化。

代码语言:javascript复制
//List转Set
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>(list);

//Set转List
Set<String> set = new HashSet<>();
List<String> list_1 = new ArrayList<>(set);

注意:这里list与set相互独立,改变其中一个不会影响另一个。

2. Array与List互转

注意引用的情况。

代码语言:javascript复制
//Array转List
String[] s = new String[]{"A", "B", "C", "D","E"};
List<String> list = Arrays.asList(s);//s改变会影响list
List<String> 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<String> 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<Integer> list = 
int[] i = 

0 人点赞