很多朋友对于深度挖掘:集合1的创新与探索和不太懂,今天就由小编来为大家分享,希望可以帮助到大家,下面一起来看看吧!
Java容器类库的目的是“保存对象”,并将其分为两个不同的概念:
收藏
一组通常遵循某些规则的“独立”元素
1.1) 列表必须保持元素的特定顺序
1.2) Set不能有重复元素
1.3)Queue维护一个队列(先进先出)顺序Map
一组成对的‘key-value’对象集合框架图:
1536558233404.jpg 简化图:
1536558265877.jpgSet、List和Map可以看作集合的三大类:
List集合是一个有序集合。集合中的元素可以重复。可以根据元素的索引来访问集合中的元素。
集合是一个无序的集合。集合中的元素不能重复。集合中的元素只能根据元素本身来访问(这也是集合中的元素不允许重复的原因)。
Map集合中以Key-value对的形式存储元素。访问时只能根据各个元素的key来访问value。
概括:
1536558418100.jpg 1.集合是一个接口,是一个高度抽象的集合,它包含了集合的基本操作和属性。 Collection包含两个分支:List和Set。
(1)List是一个有序队列,每个元素都有其索引。第一个元素的索引值为0。List的实现类有LinkedList、ArrayList、Vector和Stack。
(2)集合是不允许有重复元素的集合。 Set的实现类包括HastSet和TreeSet。 HashSet依赖于HashMap,实际上是通过HashMap来实现的; TreeSet依赖于TreeMap,而TreeMap实际上是通过TreeMap来实现的。
2.Map是映射接口,即键值对。 Map中的每个元素都包含“一个键”和“该键对应的值”。 AbstractMap是一个抽象类,它实现了Map接口中的大部分API。 HashMap、TreeMap和WeakHashMap都继承自AbstractMap。虽然Hashtable继承自Dictionary,但它实现了Map接口。
3.Iterator,它是遍历集合的工具,也就是我们通常通过Iterator来遍历集合。我们说Collection依赖于Iterator,因为Collection的所有实现类都必须实现iterator()函数并返回一个Iterator对象。 ListIterator是专门为遍历List而存在的。
4.枚举,它是JDK 1.0中引入的抽象类。功能和Iterator一样,也是遍历集合;但Enumeration的功能比Iterator少。在上面的框图中,Enumeration只能用在Hashtable、Vector和Stack中。
5.数组和集合。它们是操作数组和集合的两个工具类。
收藏
Collection接口是处理对象集合的根接口,它定义了许多操作元素的方法。 Collection接口有两个主要子接口:List和Set。请注意,Map 不是Collection 的子接口。
Collection接口中的方法如下:
1536558946854.jpg 常用的方法有以下几种:
例如,方法add()向集合中添加一个元素;
addAll() 将指定集合中的所有元素添加到集合中;
contains()方法检查集合是否包含指定元素;
toArray() 方法返回一个表示集合的数组。
另外,Collection中还有一个iterator()函数,其作用是返回一个Iterator接口。
通常,我们使用Iterator来遍历集合。 ListIterator 是List 接口所独有的。在List接口中,通过ListIterator()返回一个ListIterator对象。
Collection接口有两个常用的子接口,下面详细介绍。
列表界面
List集合表示一个有序集合,集合中的每个元素都有其对应的顺序索引。 List集合允许使用重复元素,并且可以通过索引访问指定位置的集合元素。
List接口继承自Collection接口,它可以定义一个允许重复的有序集合。因为List中的元素是有序的,所以我们可以通过索引(List中元素的位置,类似于数组下标)来访问List中的元素,这与Java的数组类似。
List接口是Collection的直接接口。 List表示一个有序的Collection,即它使用特定的插入顺序来维护元素的顺序。用户可以精确控制列表中每个元素的插入位置,并且可以根据元素的整数索引(列表中的位置)访问元素并在列表中搜索元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
1)数组列表
ArrayList是一个动态数组,也是我们最常用的集合。它允许插入任何符合规则的元素,甚至是null。每个ArrayList都有一个初始容量(10),它代表数组的大小。随着容器中的元素不断增加,容器的大小也会增大。每次将元素添加到容器时,都会检查容量。当即将溢出时,容量就扩大。因此,如果我们知道要插入的元素数量,最好指定一个初始容量值,以避免过多的扩容操作浪费时间和效率。
size、isEmpty、get、set、iterator 和listIterator 操作都在固定时间内运行。添加操作以摊余常数时间运行,即添加n 个元素需要O(n) 时间(出于缩放考虑,它不仅仅是以摊余常数时间成本添加元素那么简单)。
ArrayList擅长随机访问。同时ArrayList是异步的。
(2)链表
LinkedList也实现了List接口,与ArrayList不同。 ArrayList是一个动态数组,而LinkedList是一个双向链表。所以除了ArrayList的基本操作方法之外,它还在LinkedList的头部或尾部额外提供了get、remove、insert方法。
由于实现方式不同,LinkedList不能随机访问,它的所有操作都必须根据双向链表的需要来进行。列表中的索引操作将从开头或结尾(从更靠近指定索引的结尾)遍历列表。这样做的好处是可以以较低的成本在List中进行插入和删除操作。
与ArrayList 一样,LinkedList 也是异步的。如果多个线程同时访问一个List,它们必须自己实现访问同步。一种解决方法是在创建列表时构造一个同步列表:
列表列表=Collections.synchronizedList(new LinkedList(.));
(3)矢量
与ArrayList类似,但Vector是同步的。所以Vector是一个线程安全的动态数组。其操作与ArrayList几乎相同。
(4)堆栈
Stack继承自Vector,实现了后进先出的堆栈。 Stack 提供了5 个附加方法,允许Vector 用作堆栈。基本的push和pop方法,以及peek方法,获取栈顶的元素,empty方法测试栈是否为空,search方法检测元素在栈中的位置。堆栈创建后是一个空堆栈。
设置界面
Set是一个不包含重复元素的集合。它维护自己的内部顺序,因此随机访问没有意义。与List 一样,它也允许null 存在,但只能有一个。由于Set接口的特殊性,传入Set集合的所有元素必须是不同的。同时,应注意任何可变对象。如果是在对集合中的元素进行操作时导致e1.equals(e2)==true的话,那么肯定会出现一定的问题。 Set接口有3个具体的实现类,分别是哈希集HashSet、链式哈希集LinkedHashSet和树集TreeSet。
Set是一种不包含重复元素且无序的Collection,即任意两个元素e1和e2都有e1.equals(e2)=false,并且Set最多有一个空元素。需要注意的是,虽然Set中的元素没有顺序,但是元素在Set中的位置是由元素的HashCode决定的,其具体位置实际上是固定的。
另外,需要注意的是,set接口中有不重复的特殊要求。
举个例子, 对象A和对象B本来是两个不同的对象。一般情况下,都可以放入Set中,但是如果对象A和B都重写了hashcode和equals方法,并且重写了最终的hashcode和equals方法是一样的。那么A和B就不能同时放入Set集合中,即Set集合中的去重和hashcode与equals方法直接相关。
(1)哈希集
HashSet是一个没有重复元素的集合。它是由HashMap实现的,不保证元素的顺序(这里无顺序是指:元素插入的顺序与输出的顺序不一致),而HashSet允许使用null元素。 HashSet是异步的,如果多个线程同时访问一个哈希集,并且至少有一个线程修改了该集合,那么它必须保持外部同步。 HashSet按照Hash算法存储集合的元素,因此具有良好的访问和搜索性能。
HashSet的实现大致如下。元素存储在HashMap 中。元素存储在HashMap的Key中,Value使用Object对象。
HashSet使用和理解的常见误区:
a.HashSet中存储空值
HashSet中允许存储空值,但HashSet中只能存储一个空值。
b.HashSet中元素存储的位置是固定的
HashSet 中存储的元素是无序的。对此,没什么好说的。但由于HashSet底层是基于Hash算法实现的,并且使用的是hashcode,因此HashSet中对应元素的位置是固定的。
c.必须小心处理可变对象。如果Set 中的可变元素更改其状态导致Object.equals(Object)=true,则会导致一些问题。
(2)LinkedHashSet
LinkedHashSet继承自HashSet,其底层基于LinkedHashMap实现,是有序的、异步的。 LinkedHashSet集合还根据元素的hashCode值确定元素的存储位置,但它也使用链表来维护元素的顺序。这使得元素看起来是按插入顺序存储的,即在遍历集合时,LinkedHashSet 会按照添加的顺序访问集合的元素。
(3)树集
TreeSet是一个有序集合,其底层基于TreeMap实现,并且不是线程安全的。 TreeSet 确保集合元素已排序。 TreeSet支持自然排序和自定义排序两种排序方式,其中自然排序是默认排序方式。当我们构造一个TreeSet时,如果我们使用一个不带参数的构造函数,那么TreeSet就会使用一个自然的比较器;如果用户需要使用自定义比较器,则需要使用带比较器的参数。
注意:TreeSet集合不通过hashcode和equals函数来比较元素。它使用compare或compareTo函数来确定元素是否相等。比较函数确定两个对象的id。相同id则判断为重复元素,不会添加。到收藏。
地图界面
Map 与List 和Set 接口不同。它是由一系列键值对组成的集合,提供从键到值的映射。同时,它不继承Collection。在Map中,它保证了key和value之间的一一对应。也就是说一个key对应一个value,所以不能有相同的key值,但是value值当然可以相同。
1536559626995.jpg1.HashMap
它是用哈希表数据结构实现的。当搜索一个对象时,它的位置是通过哈希函数计算的。它是为快速查询而设计的。它内部定义了一个哈希表数组(Entry[]表),元素通过哈希转换函数传递。将元素的哈希地址转换为存储在数组中的索引。如果存在冲突,则使用哈希链表将具有相同哈希地址的所有元素串在一起。您可以查看HashMap.Entry的源代码,它是一个单链表结构。
2.LinkedHashMap
LinkedHashMap是HashMap的子类。它保留插入顺序。如果输出顺序需要与输入顺序相同,则使用LinkedHashMap。
LinkedHashMap 是Map 接口的哈希表和链表实现,具有可预测的迭代顺序。该实现提供了所有可选的映射操作并允许空值和空键。此类不保证映射的顺序,特别是它不保证顺序是不可变的。
LinkedHashMap 实现与HashMap 的不同之处在于,后者维护一个遍历所有条目的双向链表。该链表定义了迭代顺序,可以是插入顺序或访问顺序。
根据链表中元素的顺序,可以分为:按插入顺序的链表和按访问顺序的链表(调用get方法)。默认是按插入顺序排序。如果指定按访问顺序排序,那么调用get方法后,本次访问的元素会被移动到链表的末尾。连续访问可以形成按访问顺序排序的链表。
请注意,此实现不是同步的。如果多个线程同时访问链接的哈希映射,并且至少其中一个线程在结构上修改了该映射,则它必须保持外部同步。
由于LinkedHashMap需要维护元素的插入顺序,所以它的性能比HashMap略低,但由于它使用链表来维护内部顺序,因此在迭代访问Map中的所有元素时会有很好的性能。
3.树形图
TreeMap是一个有序的键值集,异步,基于红黑树(Red-Black tree)实现,每个键值节点作为红黑树的一个节点。 TreeMap在存储时会进行排序,键值对会根据key进行排序。排序方法也分为两种,一种是自然排序,另一种是定制排序,这取决于所使用的构建方法。
自然排序:TreeMap中的所有键必须实现Comparable接口,并且所有键应该是同一类的对象,否则会报ClassCastException。
自定义排序:定义TreeMap时,创建一个比较器对象,对所有TreeMap中的所有键值进行排序。使用自定义排序时,TreeMap 中的所有键不必都实现Comparable 接口。
TreeMap判断两个元素相等的标准:如果两个key通过compareTo()方法返回0,则认为两个key相等。
如果使用自定义类作为TreeMap中的键值,并且希望TreeMap能够正常工作,则必须重写自定义类中的equals()方法。 TreeMap中判断相等的标准是:两个键通过equals()方法返回true,通过compareTo()方法比较应该返回0。
Iterator和ListIterator详解
1.迭代器
Iterator是一个接口,它是集合的迭代器。集合可以使用Iterator来遍历集合中的元素。
Iterator提供的API接口如下:
boolean hasNext():判断集合中是否存在下一个元素。如果是,则hasNext() 方法返回true。
Object next():返回集合中的下一个元素。
voidremove():删除集合中最后一个next方法返回的元素。
注意:
(1)迭代器只能向一个方向移动。
(2) Iterator.remove() 是迭代过程中修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改基本集合,将会发生未知的行为。并且每次调用next()方法时,remove()方法只能调用一次。如果违反此规则,将引发异常。
列表迭代器
ListIterator 是一个更强大的迭代器。它继承自Iterator接口,只能用于各种List类型的访问。可以通过调用listIterator()方法创建一个指向List开头的ListIterator,也可以调用listIterator(n)方法创建一个从头开始指向列表中索引为n的元素的ListIterator 。
ListIterator 可以:
(1)双向移动(向前/向后遍历)。
(2) 生成列表中迭代器所指向的当前位置的前一个和下一个元素的索引。
(3) 可以使用set()方法来替换它最后访问的元素。
(4) 可以使用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素。
一些比较:
1.ArrayList和LinkedList
(1)ArrayList实现了基于动态数组的数据结构,LinkedList实现了基于链表的数据结构。
(2)对于随机访问get和set,ArrayList肯定比LinkedList好,因为LinkedList需要移动指针。
(3)对于新增、删除操作add、remove,LinedList有优势,因为ArrayList需要移动数据。
这个要看实际情况。如果只插入或删除单条数据,ArrayList比LinkedList更快。但如果批量随机插入和删除数据,LinkedList的速度比ArrayList要好很多。因为每次向ArrayList插入一条数据时,插入点及其后面的所有数据都必须移动。
2.HashTable和HashMap
相似之处:
(1) 全部实现Map、Cloneable和java.io.Serialized接口。
(2)它们都是存储“键值对”的哈希表,并且都是使用zipper方法实现的。
差异:
(1)历史原因:HashTable是基于旧的Dictionary类,而HashMap是Java 1.2中引入的Map接口的实现。
(2)同步性:HashTable是线程安全的,也就是说它是同步的,而HashMap是线程不安全的,不是同步的。
(3)空值的处理:HashMap的键和值可以为空,HashTable的键和值不能为空。
(4)基类不同:HashMap继承自AbstractMap,而Hashtable继承自Dictionary。
Dictionary是一个抽象类,直接继承自Object类,没有实现任何接口。 Dictionary 类是在JDK 1.0 中引入的。虽然Dictionary也支持“添加键值对”、“获取值”、“获取大小”等基本操作,但它的API函数比Map少;而Dictionary一般是通过Enumeration(枚举类)来遍历的。 Map是通过Iterator来遍历的。不过,由于Hashtable也实现了Map接口,因此它同时支持Enumeration遍历和Iterator遍历。
AbstractMap是一个抽象类,它实现了Map接口的大部分API函数;为Map的具体实现类提供了极大的方便。它是JDK 1.2 中添加的新类。
(5)支持不同类型的遍历:HashMap只支持Iterator遍历。 Hashtable支持两种遍历方法:迭代器和枚举。
3. HashMap、Hashtable、LinkedHashMap 和TreeMap 的比较
Hashmap是最常用的Map。它根据key的HashCode值来存储数据。它的值可以根据key直接获取,并且具有非常快的访问速度。遍历时,获取数据的顺序是完全随机的。 HashMap最多只允许一条记录的key为Null;允许多条记录的值为Null; HashMap不支持线程同步,即多个线程可以随时同时写入HashMap;这可能会导致数据不一致。如果需要同步,可以使用Collections的synchronizedMap方法来使HashMap同步。
Hashtable与HashMap类似,只不过:不允许记录的键或值为空;它支持线程同步,即任何时候只有一个线程可以写入Hashtable,这也导致Hashtale在写入时比较慢。
LinkedHashMap保存了记录的插入顺序。使用Iterator遍历LinkedHashMap时,先获取的记录必须先插入。还可以在构建时使用参数按照应用数量进行排序。遍历时会比HashMap慢,但有一个例外。当HashMap容量较大,实际数据较小时,遍历可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只与实际数据有关,与容量无关。 HashMap的遍历速度与其容量有关。如果需要输出的顺序与输入的顺序相同,那么可以使用LinkedHashMap。也可以按读取顺序排列,比如按连接池排列。 LinkedHashMap 实现与HashMap 的不同之处在于,后者维护一个遍历所有条目的双向链表。该链表定义了迭代顺序,可以是插入顺序或访问顺序。对于LinkedHashMap来说,它继承自HashMap,底层使用哈希表和双向链表来保存所有元素。其基本操作与父类HashMap类似。它通过重写父类相关方法来实现自己的链表功能。
TreeMap实现了SortMap接口,其内部实现是一棵红黑树。它保存的记录可以根据key进行排序。默认按照键值升序排序。您还可以指定排序比较器。当使用Iterator遍历TreeMap时,得到的记录是排序的。 TreeMap不允许键值为空。异步。
一般情况下,用得最多的就是HashMap。 HashMap中存储的键值对取出来是随机的。它根据key的HashCode值来存储数据。根据key可以直接获取其值,访问速度快。速度。要在Map中插入、删除和定位元素,HashMap是最好的选择。
TreeMap取出来的是排序后的键值对。但如果你想以自然顺序或自定义顺序迭代键,那么TreeMap 会更好。
LinkedHashMap是HashMap的子类。如果需要输出顺序与输入相同,则可以使用LinkedHashMap。也可以按读取顺序排列,比如按连接池排列。
4.HashSet、LinkedHashSet、TreeSet的比较
设置界面
Set 不允许包含相同的元素。如果尝试将两个相同的元素添加到同一集合中,add 方法将返回false。
Set 不是使用==运算符,而是使用equals 方法来确定两个对象相同。也就是说,只要使用equals方法比较两个对象并返回true,Set就不会接受这两个对象。
哈希集
HashSet具有以下特点:
- 不保证元素的排列顺序,并且顺序可能会改变。
-不同步。
- 集合元素可以为null,但只能放置一个null。
当一个元素存储在HashSet组合中时,HashSet会调用该对象的hashCode()方法来获取该对象的hashCode值,然后根据hashCode值确定该对象在HashSet中的存储位置。简单来说,判断HashSet集合中两个元素相等的标准就是通过equals方法两个对象相等,并且两个对象的hashCode()方法的返回值也相等。
注意,如果要将一个对象放入HashSet 并重写该对象对应类的equals 方法,还应该重写其hashCode() 方法。规则是,如果两个对象通过equals方法比较返回true,那么它们的hashCode也应该相同。另外,应该使用对象中用作equals 的标准属性来计算hashCode 的值。
链接哈希集
LinkedHashSet集合还根据元素的hashCode值确定元素的存储位置,但它也使用链表来维护元素的顺序。这使得元素看起来是按插入顺序存储的,即在遍历集合时,LinkedHashSet 会按照添加的顺序访问集合的元素。
LinkedHashSet在迭代访问Set中所有元素时比HashSet性能更好,但在插入时性能略逊于HashSet。
树集类
TreeSet是SortedSet接口的唯一实现类。 TreeSet可以保证集合元素处于排序状态。 TreeSet支持自然排序和自定义排序两种排序方式,其中自然排序是默认排序方式。添加到TreeSet中的应该是同一类的对象
。 TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0。 自然排序 自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。 Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。obj1.compareTo(obj2)方法如果返回0,则说明被比较的两个对象相等,如果返回一个正数,则表明obj1大于obj2,如果是负数,则表明obj1小于obj2。如果我们将两个对象的equals方法总是返回true,则这两个对象的compareTo方法返回应该返回0。 定制排序 自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现 int compare(T o1,T o2)方法。【深度挖掘:集合1的创新与探索】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
期待看到这个“集合”里有什么东西!
有19位网友表示赞同!
不知道“集合1”包含了什么内容呢?让人很 Curious!
有10位网友表示赞同!
希望“集合1”里面是很多有趣的东西!
有10位网友表示赞同!
我猜 “集合1” 应该是个很好的开始。
有8位网友表示赞同!
感觉 “集合1” 充满了无限可能性!
有12位网友表示赞同!
对“集合1”充满了期待,希望能有惊喜!
有11位网友表示赞同!
这个“集合1” 一定很有意思吧?可以分享一下内容吗?
有14位网友表示赞同!
不知道 “集合1” 是由谁创建的啊?有没有背后的故事?
有7位网友表示赞同!
喜欢这种充满未知感的标题,让人想去探索 “集合1”。
有14位网友表示赞同!
简单却直白的标题,“集合1”,好期待能揭开它的秘密!
有7位网友表示赞同!
会不会 “集合1” 是个系列的开端呢?有什么后续内容吗?
有12位网友表示赞同!
希望这个“集合1” 能给我们带来新的启发和感受!
有12位网友表示赞同!
感觉 “集合1” 像是某种密码,等着我们去解开。
有20位网友表示赞同!
"集合1" 让人联想到很多不同的可能性,真有趣!
有20位网友表示赞同!
希望这个"集合1"能变得越来越丰富多彩!
有20位网友表示赞同!
这个标题很抓人眼球,让我迫切地想知道 “集合1” 的具体内容!
有5位网友表示赞同!
感觉 "集合1" 很有个人的风格,值得一探究竟!
有16位网友表示赞同!
"集合1" 是不是一个特别的主题?很想了解它的背景故事。
有5位网友表示赞同!
这个标题让我想到许多创意的可能性,期待 “集合1” 的出现!
有6位网友表示赞同!