1、Iterator的并发修改异常
运行代码时发生了错误 java.util.ConcurrentModificationException[并发修改异常]这是什么原因呢?
在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。
并发修改异常解决办法:在迭代时,不要使用集合的方法操作元素。
那么想要在迭代时对元素操作咋办?通过ListIterator迭代器操作元素是可以的,ListIterator的出现,解决了使用Iterator迭代过程中可能会发生的错误情况。
2、Java中三种长度表现形式
数组.length 属性 返回值 int
字符串.length() 方法,返回值int
集合.size()方法, 返回值int
3、 equals() 与 == 的区别是什么?
== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不试同一个对象。
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况(前面第1部分已详细介绍过):
情况1,类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况2,类覆盖了equals()方法。一般,我们都覆盖equals()方法来两个对象的内容相等;若它们的内容相等,则返回true(即,认为这两个对象相等)。
4、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
Java对于eqauls方法和hashCode方法是这样规定的:
(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
(2)如果两个对象的hashCode相同,它们并不一定相同。
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。
哈希冲突:不同的键值对,哈希值相等
hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。但是只有在HashSet, Hashtable, HashMap等等这些本质是散列表的数据结构中,这个方法才有用
eqauls方法
Object.java中定义了equals()方法,这就意味着所有的Java类都实现了equals()方法,此时定义的equals()方法的功能与“==”一样,都是根据地址判断是否是同一个对象。
当我们对equals()方法进行重写之后,equals()方法的功能就是判断两个对象的内容是否相等。相等返回true
“==”一直都是根据地址判断两个对象是否相等
5、数据存储常用结构
堆栈、队列、数组、链表
堆栈:先进后出,栈的出口入口都是栈的顶端
队列:先进先出,队列的入口、出口各占一列
数组:查找元素快(通过索引),增删元素慢(都需要创建新数组然后进行增加和删除操作)
链表:多个节点通过地址进行连接
查找元素慢,添加元素快
6、Collection 、Collections、List、Set的区别
List与Set都继承于Collection,Collection是集合的顶级接口。而Collections是集合工具类。
list为有序集合接口,ArrayList、LinkedList、Vector为其实现类;
Set是无序不重复集合接口,HashSet、LinkedHashSet、TreeSet为其实现类
7、ArrayList、LinkedList、Vector的区别【List有序集合】
list为有序集合接口,ArrayList、LinkedList、Vector为其实现类;
ArrayList和 Vector:底层为数组、查询快、增删慢 。
ArrayList :底层为数组、查询快、增删慢 。由于开发中最多的功能就是查询数据、遍历数据,所以ArrayList是最常用的集合。效率高、线程不安全;
Vector:底层为数组、查询快、增删慢 。效率低、线程安全。线程安全的原因:使用了synchronize进行同步写数据,但是开销比较大,所以vector是一个同步容器并不是一个并发容器。
LinkedList:底层为链表结构、查询慢、增删快。【LinkedList插入,删除都是移动指针效率很高;
查找需要进行遍历查询,效率较低】
8、哈希表
什么是哈希表呢?
哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放时,那么会根据这些对象的特有数据结合相应的算法,计算出这个对象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。
当向哈希表中存放元素时,需要根据元素的特有数据结合相应的算法,这个算法其实就是Object类中的hashCode方法。由于任何对象都是Object类的子类,所以任何对象有拥有这个方法。即就是在给哈希表中存放对象时,会调用对象的hashCode方法,算出对象在表中的存放位置,这里需要注意,如果两个对象hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中。
【算法计算出来的数据是这个对象在数组中存放的位置。。。。。由于是set集合,元素是不重复的,所以当两个对象---这里的两个对象肯定是不相同的----哈希值相同时,称之为哈希冲突,这个时候会调用对象的】
总结:保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。
说重点
简单叙述哈希表结构存储数据的原理:
哈希表底层使用的是数组机制,数组中存放对象。这些对象的存放位置有些特殊。
当我们向哈希表中存放元素的时候,需要根据特有的数据结合hashCode()方法计算出这个对象在数组中的存放位置
注意:如果两个对象hashCode()方法算出的结果一样,这种现象称之为哈希冲突。这个时候会调用对象的equals()方法,比较这两个对象是不是同一个对象,如果equals()方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中
9、HashSet、LinkedHashSet、TreeSet
Set是无序不重复集合接口,HashSet、LinkedHashSet、TreeSet为其实现类
HashSet底层结构是哈希表结构,元素唯一不能重复。(如何保证元素的唯一性:重写hashCode()与equals()方法)【hashSet原理比较简单,几乎全部借助于hashMap来实现的。所以HashMap会出现的问题HashSet依然不能避免】
LinkedHashSetHashSet的一个子类,底层存储结构式链表和哈希表组合,保证元素的唯一性和有序性。(元素的存与取得顺序一致)
10、判断集合元素唯一的原理
10.1、ArrayList的contains()方法判断元素是否重复原理
ArrayList的contains()方法会使用调用方法时,传入的元素的equals方法依次与集合中的旧元素所比较,从而根据返回的布尔值判断是否有重复元素。此时,当ArrayList存放自定义类型时,由于自定义类型在未重写equals方法前,判断是否重复的依据是地址值,所以如果想根据内容判断是否为重复元素,需要重写元素的equals方法。
注意:List集合可以存放重复元素,所以ArrayList的contains()方法会使用调用方法时,传入的元素的equals()方法依次与集合中的旧元素所比较,从而根据返回的布尔值判断是否有重复元素。
10.2、HashSet的add/contains等方法判断元素是否重复原理
注意:Set集合元素不能重复,所以contains()不行。需要重写hashCode()方法和equals()方法
11、Map接口
11.1、Map接口中的常用方法
11.2、Map集合遍历方式
方式一:Map集合遍历键找值方式
代码实现
方式二:Map集合遍历键值对方式 Entry键值对对象 遍历键找值 代码实现
注意:两种方式对比建议使用遍历键值对找值。因为遍历键值对找值可以把key,value同时取出,使用遍历键找值还需要通过key取一次value,效率较低
12、HashMap、HashTable
Map集合元素都是以键值对的形式存取
键不能重复,值可以重复
12.1、HashMap:
特点:
是Map集合的子集合
底层基于数组和链表实现的
HashMap集合中的key不能重复,通过重写hashCode() 与 equals()方法来保证键的唯一。
不能保证元素存与取的顺序完全一致
HashMap的效率高、线程不安全、允许键或值为空
注意:在并发情况下使用hashMap容易出现死循环(并发情况下发生扩容时会出现环形链表)。并发场景发生扩容的时候,所以hashMap只能在单线程中使用
重点
由于hashMap是一个线程不安全的容器,主要是当容量发生扩容的时候会出现环形链表从而导致死循环。(当容量大于总量*负载因子时)
因此需要支持线程安全的并发容器
ConcurrentHashMap
12.2、 LinkedHashMap
LinkedHashMap:
特点:
是HashMap集合的子集合
底层采用哈希表+链表结构
LinkedHashMap集合中的key不能重复,通过重写hashCode() 与 equals()方法来保证键的唯一。
HashMap、HashTable
HashMap的效率高、线程不安全、允许键或值为空
HashTable线程安全、效率低、不允许键或值为空
网友评论