从0开始回顾Java---系列七

简介: 引言1、常见集合有哪些?Java集合类主要由两个根接口Collection和Map派生出来的,Collection派生出了三个子接口:List、Set、Queue,因此Java集合大致也可分成List、Set、Queue、Map四种接口体系。● List代表了有序可重复集合,可直接根据元素的索引来访问;● Set代表无序不可重复集合,只能根据元素本身来访问;● Queue是队列集合。● Map代表的是存储key-value对的集合,可根据元素的key来访问value。2、线程安全的集合有哪些?线程不安全的呢?线程安全的:● Hashtable:比HashMap多了个线

引言

1、常见集合有哪些?


Java集合类主要由两个根接口CollectionMap派生出来的,Collection派生出了三个子接口:List、Set、Queue,因此Java集合大致也可分成List、Set、Queue、Map四种接口体系。

  • List代表了有序可重复集合,可直接根据元素的索引来访问;
  • Set代表无序不可重复集合,只能根据元素本身来访问;
  • Queue是队列集合。
  • Map代表的是存储key-value对的集合,可根据元素的key来访问value。


2、线程安全的集合有哪些?线程不安全的呢?

线程安全的:

  • Hashtable:比HashMap多了个线程安全。
  • ConcurrentHashMap:是一种高效但是线程安全的集合。
  • Vector:比Arraylist多了个同步化机制。
  • Stack:栈,也是线程安全的,继承于Vector。

线性不安全的:

  • HashMap
  • Arraylist
  • LinkedList
  • HashSet
  • TreeSet
  • TreeMap

List

1、Set与List区别?

  1. List,Set都是继承自Collection接口
  2. List特点:添加的元素是有序,可重复,有索引 。Set特点添加的元素是无序,不重复,无索引的,重复元素会覆盖掉。
  3. List支持for循环遍历,也可以用迭代器,但是set没有for循环遍历方法,因为set是无索引的,无法用下标来取得想要的值。
  4. Set和List效率对比
  • Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
  • List:和数组类似,查找元素效率高,插入和删除元素效率低,因为会引起其他元素位置改变。

2、讲一讲ArrayList?

  1. ArrayList 是容量可变的非线程安全列表,使用数组实现,集合扩容时会创建更大的数组,把原有数组复制到新数组。支持对元素的快速随机访问,即可以通过元素的序号快速获取元素对象,但是插入与删除速度很慢。
  2. 构造函数 以无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量,即向数组中添加第一个元素时,数组容量扩为 10。
  3. 扩容 看下一个问题
  4. 删除元素 需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,在旧数组上操作,该操作的时间复杂度为 O(N),可以看到 ArrayList 删除元素的代价是非常高的。
  5. 序列化ArrayList的序列化不太一样,它使用transient修饰存储元素的elementData的数组,transient关键字的作用是让被修饰的成员属性不被序列化
  6. Fail-Fast:快速失败,modCount 用来记录 ArrayList 结构发生变化的次数,结构发生变化是指添加或者删除至少一个元素的操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,改变了则抛出 ConcurrentModificationException(并发修改)异常。


3、ArrayList的扩容机制了解吗?


当容量不够时,需要使用grow()方法进行扩容,新容量的大小为 oldCapacity + (oldCapacity >> 1)oldCapacity >> 1 需要取整,所以新容量大约是旧容量的 1.5 倍左右,即 oldCapacity+oldCapacity/2

扩容操作需要调用 Arrays.copyOf()(底层 System.arraycopy())需要把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数


4、为什么ArrayList不直接序列化元素数组呢?


出于效率的考虑,数组可能长度100,但实际只用了50,剩下的50其实不用序列化,这样可以提高序列化和反序列化的效率,还可以节省内存空间

5、ArrayList 与Vector区别?

  1. 实现都实现了List接口,底层都使用 Object[]数组存储。
  2. 线程安全: Vector使用了Synchronized 来实现线程同步,是线程安全的,而 ArrayList是非线程安全的。
  3. 扩容 Vector 每次扩容请求其大小的 2 倍(也可以通过构造函数设置增长的容量),而 ArrayList 是 1.5 倍。
  4. 性能:  ArrayList在性能方面要优于Vector。


6、为什么要用Arraylist取代Vector?


Vector 是同步的,开销比 ArrayList 要大,访问速度更慢。最好使用 ArrayList 而不是 Vector,是因为同步操作完全可以由程序来控制。


7、讲讲LinkedList?


  1. LinkedList 是一个实现了 List 接口的双端链表,支持高效的插入和删除操作,另外也实现了 Deque 接口,使得 LinkedList 类也具有队列的特性。
  2. LinkedList 包含三个重要的成员:size、first 和 last。size 是双向链表中节点的个数,first 和 last 分别指向首尾节点的引用。
  3. LinkedList 的优点在于可以将零散的内存单元通过附加引用的方式关联起来,形成按链路顺序查找的线性结构,内存利用率较高。


8、ArrayList和LinkedList的区别?


  1. 是否保证线程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全
  2. 底层数据结构
  • Arraylist 底层使用的是 Object 数组,默认初始大小为10,插入元素超出则会动态扩容为原来的1.5倍。
  • LinkedList 底层使用的是双向链表数据结构(JDK1.6 之前为循环链表,JDK1.7 取消了循环)
  1. 插入和删除是否受元素位置的影响
  • ArrayList 采用数组存储,所以插入和删除元素受元素位置的影响
  • LinkedList采用链表存储,所以插入和删除元素不受元素位置的影响
  1. 是否支持快速随机访问
  • LinkedList 不支持高效的随机元素访问,ArrayList 支持
  • 快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。
  1. 内存空间占用:
  • ArrayList是预先定义好的数组,可能会有空的内存空间,存在一定空间浪费。
  • LinkedList每个节点,需要存储前驱和后继,所以每个节点会占用更多的空间


相关文章
|
5天前
|
存储 缓存 安全
从0开始回顾Java---系列四
String 1、String 是 Java 基本数据类型吗?可以被继承吗?为什么? String是Java基本数据类型吗? 不是。Java 中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type)。 String是一个比较特殊的引用数据类型。 String 类可以继承吗? 不行。String 类使用 final 修饰,是所谓的不可变类,无法被继承。 String 类为什么要被设计成不可继承? 1. 字符串是一种非常重要且常用的数据类型
|
5天前
|
存储 安全 算法
从0开始回顾Java---系列九
TreeMap 1、TreeMap 有什么特点? 1. TreeMap是基于红黑树的一种提供顺序访问的Map,增删改查的平均和最差时间复杂度均为 O(logn) ,最大特点是 Key 有序。 2. Key 必须实现 Comparable 接口或提供的 Comparator 比较器,所以 Key 不允许为 null。 3. TreeMap是一个线程不安全,有序的键值对集合,因为TreeMap实现了SotredMap接口。 4. TreeMap实现了Cloneable接口,可被克隆,实现了Serializable接口,可序列化; 2、讲讲 TreeMap 怎么实现有序的? TreeMap
|
5天前
|
缓存 Java 调度
从0开始回顾Java---系列五
Integer 1、Integer a= 127,Integer b = 127;Integer c= 128,Integer d = 128;相等吗? 答案是a和b相等,c和d不相等。 ● 对于基本数据类型==比较的值 ● 对于引用数据类型==比较的是地址 Integer a= 127这种赋值,是用到了Integer自动装箱的机制。自动装箱的时候会去缓存池里取Integer对象,没有取到才会创建新的对象。 如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用缓存池中的Integer对象,超过范围 a1==b1的结果是false。 publi
|
5天前
|
JSON Java 编译器
从0开始回顾Java---系列六
IO 1、Java中IO流分为几种? 流按照不同的特点,有很多种划分方式: • 按照流的流向分,可以分为输入流和输出流; • 按照操作单元划分,可以划分为字节流和字符流; • 按照流的角色划分为节点流和处理流。 Java Io流共涉及40多个类,看上去杂乱,其实都存在一定的关联, Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。 • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。 • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。 IO流用到了什么设计模式? 装饰器模式 2、既
|
5天前
|
存储 安全 Java
从0开始回顾Java---系列三
面向对象 1、谈一谈你对面向对象的理解 ? 面向过程: 一件事该怎么做,注重实现过程,以过程为中心; 面向对象: 实现对象是谁,只关心怎样使用,不关心具体实现(只关心实现对象是谁,有封装、继承、多态三大特性); 总结: ● 面向对象是一种编程思想,早期的面向过程的思想就是一件事该怎么做,而面向对象就是一件事该由谁来做,它怎么做的我不管,我只需要调用就行。而这些是由面向对象的三大特性来实现的,三大特性就是封装、继承、多态。 2、面向对象的三大特性? 封装:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法。 多态: 所谓多态就是指程序中定义的引用变量所指
|
5天前
|
存储 安全 算法
从0开始回顾Java---系列八
HashMap 1、HashMap 有什么特点? HashMap 基于哈希表的 Map 接口实现,是以 key-value 存储形式存在,主要用来存放键值对。 特点: ● HashMap 的实现不是同步的,这意味着它不是线程安全的 ● key 是唯一不重复的,底层的哈希表结构,依赖 hashCode 方法和 equals 方法保证键的唯一 ● key、value 都可以为null,但是 key 位置只能是一个null ● HashMap 中的映射不是有序的,即存取是无序的 ● key 要存储的是自定义对象,需要重写 hashCode 和 equals 方法,防止出现地址不同内
|
Java 编译器
强哥说Java--Java基础
强哥说Java--Java基础
61 0
|
存储 Java 开发者
[Java --- List]
我们之前实现过的顺序表,只能保存 int 类型的元素,如果现在需要保存 指向 Person 类型对象的引用的顺序表,请问应该如何解决?如果又需要保存指向 Book 对象类型的引用呢?
|
Java
Java报错:Cause: java.io.NotSerializableException: xxx 解决方案
原因是实体类没有开启序列化接口导致的 开启实体类序列化接口即可:
110 0
|
Java 编译器
Java---继承
继承的基本思想是,基于已有的类创造新的类。继承已存在的类就是复用这些类的方法,而且可以增加一些新的方法和字段,使新类能够适应新的情况,继承是Java程序设计中一项核心技术,它主要解决的问题是:共性的抽取,实现代码复用。
Java---继承