Java基础之容器

容器基本概念

Collection:中文译为容器或集合。
数组是简单的序列,它的效率高,但是它不够灵活。
容器中:set是无序序列,而且内容不可以重复;而list是有顺序的,是可以重复的。
在这里插入图片描述

泛型(Generics)

泛型相当于容器的标签,它可以帮助我们建立类型安全的集合。在使用了泛型的集合中,遍历时不必进行强制类型转换。JDK提供了支持泛型的编译器,将运行时的类型检查提前到了编译时执行,提高了代码可读性和安全
泛型的本质就是“数据类型的参数化”。 我们可以把“泛型”理解为数据类型的一个占位符(形式参数),即告诉编译器,在调用泛型时必须传入实际类型。
可在类的声明处增加泛型列表,如:<T,E,V>。 此处,字符可以是任何标识符,一般采用这3个字母。
容器相关类都定义了泛型,我们在开发和工作中,在使用容器类时都要使用泛型。这样,在容器的存储数据、读取数据时都避免了大量的类型判断,非常便捷。

由于List、Set是Collection的子接口,意味着所有List、Set的实现类都有上面的方法。了解并掌握Collection的主要方法,并学会看源码。

Set接口

Set接口继承自Collection,Set接口中没有新增方法,方法和Collection保持完全一致。 Set常用的实现类有:HashSet、TreeSet等,一般使用HashSet。(Set中也只能放入一个null元素,不能多个)
HashSet是采用哈希算法实现,底层实际是用HashMap实现的(HashSet本质就是一个简化版的HashMap),因此,查询效率和增删效率都比较高。

掌握多个集合之间的操作方法
在这里插入图片描述

注意掌握ArrayList索引和顺序的相关方法以及ArrayList底层实现和了解源码分析:

ArrayList底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。我们一般使用它。查看源码:ArrayList底层使用Object数组来存储元素数据。所有的方法,都围绕这个核心的Object数组来开展。ArrayList是可以存放任意数量的对象,长度不受限制,通过扩容实现。ArrayList底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。我们一般使用它。查看源码:
LinkedList底层用双向链表实现的存储。特点:查询效率低,增删效率高,线程不安全。 双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。 所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。
Vector底层是用数组实现的List,相关的方法都加了同步检查,因此“线程安全,效率低”。 比如,indexOf方法就增加了synchronized同步标记。
Map

Map就是用来存储“键(key)-值(value) 对”的。 Map类中存储的“键值对”通过键来标识,所以“键对象”不能重复。Map中的信息成对存储。 Map 接口的实现类有HashMap、TreeMap、HashTable、Properties等。

HashMap

HashMap采用哈希算法实现,是Map接口最常用的实现类。 由于底层采用了哈希表存储数据,我们要求键不能重复,如果发生重复,新的键值对会替换旧的键值对。 HashMap在查找、删除、修改方面都有非常高的效率。
HashMap线程不安全,但效率高,允许key或value为null。

HashMap底层实现

HashMap底层实现采用了哈希表的数据结构(redis数据库的核心技术和HashMap一样),哈希表的本质就是数组+链表(单向链表)。
在HashMap的底层源码中有一个Node[] table,这个就是它的核心数组结构。它也常被称为“位桶数组”。
一个Node对象存储了以下属性;

  1. key:键对象 value:值对象
  2. next:下一个节点
  3. hash: 键对象的hash值

显然每一Node对象就是一个单向链表结构,我们使用图形表示一个Node对象的典型示意:
存储结构图

Node[] 数组结构
HashMap核心结构
了解HashMap存储数据的过程,知道它是如何产生hash值,该值是用来对应数组的存储结构。哈希码不一样,可能哈希值相同。

我们的目的是将”key-value两个对象”成对存放到HashMap的Entry[]数组中。参见以下步骤:
(1) 获得key对象的hashcode
首先调用key对象的hashcode()方法,获得hashcode。
(2) 根据hashcode计算出hash值(要求在[0, 数组长度-1]区间)
hashcode是一个整数,我们需要将它转化成[0, 数组长度-1]的范围。我们要求转化后的hash值尽量均匀地分布在[0,数组长度-1]这个区间,减少“hash冲突”。
了解常见的Hash算法,
(3) 生成Entry对象
如上所述,一个Entry对象包含4部分:key对象、value对象、hash值、指向下一个Entry对象的引用。我们现在算出了hash值。下一个Entry对象的引用为null。
(4) 将Entry对象放到table数组中
如果本Entry对象对应的数组索引位置还没有放Entry对象,则直接将Entry对象存储进数组;如果对应索引位置已经有Entry对象,则将已有Entry对象的next指向本Entry对象,形成链表。

注意: JDK8中,HashMap在存储一个元素时,当对应链表长度大于8时,链表就转换为红黑树,这样又大大提高了查找的效率。

HashTable

HashTable类和HashMap用法几乎一样,底层实现几乎一样,只不过HashTable的方法添加synchronized关键字确保线程同步检查,效率较低。
HashTable线程安全,但效率低,不允许key或value为null。

TreeMap

TreeMap是红黑二叉树的典型实现。(可以看看数据结构中二叉树的相关内容),打印时可以 自动根据key排序。
HashMap效率高于TreeMap;在需要排序的Map时才选用TreeMap。
了解Comparable这个接口。也可以通过实现这个接口来达到我们自己想要的排序方法

迭代器(Iterator)

迭代器提供了统一的遍历容器的方式。
迭代器中有hasNext()和next()方法。
了解并掌握用迭代器遍历List,Set和Map;

####### Collections工具类
类 java.util.Collections 提供了对Set、List、Map进行排序、填充、查找元素的辅助方法。
1. void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。
2. void shuffle(List) //对List容器内的元素进行随机排列。
3. void reverse(List) //对List容器内的元素进行逆续排列 。
4. void fill(List, Object) //用一个特定的对象重写整个List容器。
5. int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象。
注意:Colletion是 接口,Colllections是工具类,不要把二者弄混了。

使用容器存储表格数据

第一种方法:
用map代表一行数据
用List代表一整个表格的数据。
第二种方法:
用JavaBean代表一行数据;
将整个表格数据用map或者List存储。

猜你喜欢

转载自blog.csdn.net/qq_35383654/article/details/85237346
今日推荐