Java容器的理解

 容器,顾名思义,它是用来装载其他东西的。

 在Java中,定义了一个Collection接口,定义了三个子接口,分别是Set,Map,List,并将它们实现为类;

下面就分别来介绍这三种常见容器,首先是Set ,Set 作为一个集合的概念来理解,它里面的内容没有固定顺序,不可以重复,常见的Set有HashSet;

接下来是Map ,定义了key-value,键值对的存储方法;

Java中数据存储方式最底层的两种结构,一种是数组,另一种就是链表,数组的特点:连续空间,寻址迅速,但是在删除或者添加元素的时候需要有较大幅度的移动,所以查询速度快,增删较慢。而链表正好相反,由于空间不连续,寻址困难,增删元素只需修改指针,所以查询慢、增删快。

哈希表。哈希表具有较快(常量级)的查询速度,及相对较快的增删速度,所以很适合在海量数据的环境中使用。一般实现哈希表的方法采用“拉链法”,我们可以理解为“链表的数组”

常见的hashMap和hashTable,

HashMap的存储规则:

哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。如果出现Hash冲突, 将在数组的该位置拉伸出链表进行存储(在链表的尾部进行添加), 如果链表的长度大于设定值后, 将链表转为红黑树.

 下面来看一下它常见的

源码一

1 public HashMap() {  
2         this.loadFactor = DEFAULT_LOAD_FACTOR;     //装载因子
3         threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);       
4         table = new Entry[DEFAULT_INITIAL_CAPACITY];  //起始容量 
5         init();  
6     }  

   

源码二

 1 public HashMap(int initialCapacity, float loadFactor) {  
 2         if (initialCapacity < 0)    //判断是否合法
 3             throw new IllegalArgumentException("Illegal initial capacity: " +  
 4                                                initialCapacity);  
 5         if (initialCapacity > MAXIMUM_CAPACITY)  //判断是否超过默认最大值,如果超过,改为最大值
 6             initialCapacity = MAXIMUM_CAPACITY;  
 7         if (loadFactor <= 0 || Float.isNaN(loadFactor))    //装载因子
 8             throw new IllegalArgumentException("Illegal load factor: " +  
 9                                                loadFactor);  
10   
11         // Find a power of 2 >= initialCapacity  
12         int capacity = 1;  
13         while (capacity < initialCapacity)  
14             capacity <<= 1;  
15   
16         this.loadFactor = loadFactor;  
17         threshold = (int)(capacity * loadFactor);  
18         table = new Entry[capacity];  
19         init();  
20     }  

 

HashTable的存储规则:

优先使用数组存储, 存储元素时, 先取出下标上的元素(可能为null), 然后添加到数组元素Entry对象的next属性中(在链表的头部进行添加).

出现Hash冲突时, 新元素next属性会指向冲突的元素. 如果没有Hash冲突, 则新元素的next属性就是null

 

1、HashMap是非线程安全的,HashTable是线程安全的。

2、HashMap的键和值都允许有null值存在,而HashTable则不行。

 

HashMap

HashTable

key, value 均可以为 null

key, value 均不可以为 null

 

 

 

 

 

最后是List,它是作为链表的概念来理解,里面的元素有固定顺序,也可以重复;

它们的父接口Collection定义了一些常见的方法,比如

int size();// 返回容器的长度

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

boolean contains(Object element);//判断是否包含某一个元素

void clear(); //清空

boolean add();//添加

boolean remove();移除

Iterator接口,这是额外值得注意的东西,由于每个容器都各不相同,很难有一个统一的方法去遍历容器内的元素,因此每个容器都实现了Iterator方法,返回一个Iterator对象,可以对本身进行控制,只有容器自己,最了解容器的操作,包括遍历,删除,添加。

iterator常见的函数有:::
boolean hasNext();  //判断是否存在下一个
Object next();          //返回下一个元素
void remove();        //删除,注意,Iterator对象的remove方法是Collection在迭代过程中,删除元素唯一安全的方法。

Iterator方法的思想中也有父类引用指向子类对象的思想,Java封装性的体现。

Object[] toArray()  将Object类的链表转换为Object类的数组

 容器里常用的Java概念就是父类引用指向子类对象,经常需要重写的方法有equals()方法,hascode()方法,实现了Compare able接口的类重写compareTo()方法,

toString()方法,线程里的run方法。

泛型的由来,存入集合的元素都被当作Object类来对待,导致各个数据类型失去了自己的特性,解决的方法就是在定义容器对象的过程中,直接定义容器内元素的类型,这样程序的稳定性和可读性就好很多。

posted on 2018-09-23 10:39  zhishiyv  阅读(970)  评论(0)    收藏  举报

导航