3.2.7.1 请用ArrayList实现Stack以及Queue的功能。

public class ArrayListStack extends ArrayList implements Stack {
    ArrayList arrayList =new ArrayList<>() ;
    public void push(T obj) {
       arrayList.add(obj);
    }
    public T pop() {
        return arrayList.remove(arrayList.size()-1);
    }

public int size(){

return arrayList.size();

}
}

3.2.7.2 如果让你实现Java的ArrayList,你需要考虑哪些要素?

ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。

ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。

每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容量。在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。 
   注意,此实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。

ArrayList提供了三种方式的构造器,可以构造一个默认初始容量为10的空列表、构造一个指定初始容量的空列表以及构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列的。

ArrayList提供了set(int index, E element)、add(E e)、add(int index, E element)、addAll(Collection<? extends E> c)、addAll(int index, Collection<? extends E> c)这些添加元素的方法。

每当向数组中添加元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容,以满足添加数据的需求。数组扩容通过一个公开的方法ensureCapacity(int minCapacity)来实现。在实际添加大量元素前,我也可以使用ensureCapacity来手动增加ArrayList实例的容量,以减少递增式再分配的数量。

数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。

Fail-Fast机制: 
ArrayList也采用了快速失败的机制,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

3.2.7.3 请通过Iterator对象访问LinkedList对象,并说明这种访问方式的好处。

LinkedList  list =  new LinkedList();

//省略赋值
  ListIterator it = list.listIterator();
  while(it.hasNext()) { 
   System.out.println(it.next().toString()); //使用  
  }

好处是,能用统一的方式来访问集合对象,这也是迭代器模式的好处。

3.2.7.4 你有没有读过ArrayList部分的底层实现源代码?如果有,请说明下其中的add方法是如何实现的?尤其请考虑动态扩展的情况。

如下是扩容的底层方法

/**
* 增加ArrayList容量。
*
* @param minCapacity 想要的最小容量
*/
public void ensureCapacity(int minCapacity) {
    // 如果elementData等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,最小扩容量为DEFAULT_CAPACITY,否则为0
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY;
    //如果想要的最小容量大于最小扩容量,则使用想要的最小容量。
    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}
/**
* 数组容量检查,不够时则进行扩容,只供类内部使用。
*
* @param minCapacity 想要的最小容量
*/
private void ensureCapacityInternal(int minCapacity) {
    // 若elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,则取minCapacity为DEFAULT_CAPACITY和参数minCapacity    之间的最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

ensureExplicitCapacity(minCapacity);
}
/**
* 数组容量检查,不够时则进行扩容,只供类内部使用
*
* @param minCapacity 想要的最小容量
*/
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

// 确保指定的最小容量 > 数组缓冲区当前的长度
    if (minCapacity - elementData.length > 0)
    //扩容
    grow(minCapacity);
}

/**
* 分派给arrays的最大容量
* 为什么要减去8呢?
* 因为某些VM会在数组中保留一些头字,尝试分配这个最大存储容量,可能会导致array容量大于VM的limit,最终导致OutOfMemoryError。
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/**
* 扩容,保证ArrayList至少能存储minCapacity个元素
* 第一次扩容,逻辑为newCapacity = oldCapacity + (oldCapacity >> 1);即在原有的容量基础上增加一半。第一次扩容后,如果容量还是小于minCapacity,就将容量扩充为minCapacity。
*
* @param minCapacity 想要的最小容量
*/
private void grow(int minCapacity) {
    // 获取当前数组的容量
    int oldCapacity = elementData.length;
    // 扩容。新的容量=当前容量+当前容量/2.即将当前容量增加一半。
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果扩容后的容量还是小于想要的最小容量
    if (newCapacity - minCapacity < 0)
        //将扩容后的容量再次扩容为想要的最小容量
        newCapacity = minCapacity;
    //如果扩容后的容量大于临界值,则进行大容量分配
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
     // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData,newCapacity);
}
/**
* 进行大容量分配
*/
private static int hugeCapacity(int minCapacity) {
    //如果minCapacity<0,抛出异常
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    //如果想要的容量大于MAX_ARRAY_SIZE,则分配Integer.MAX_VALUE,否则分配MAX_ARRAY_SIZE
    return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
}

3.2.7.5 请说下Collection和Collections的差别以及各自的用途。

Collections 是一个集合的一个类,其中包含有一些和集合操作相关的静态多态方法。Jave集合里则有另外一个和它非常相似的接口

Collection(不带s),它是线性表类集合的父接口,List和Set等接口都是通过实现这个接口来实现的。

3.2.7.6 我们知道Set对象里不能有重复的元素,请说下是用什么方法来判断是否重复?是通过equals方法吗?

请参与本书3.2.3 Set集合是如何判断重复,里面有详细的描述

Java核心技术及面试指南 线性表方面的面试题总结以及答案的更多相关文章

  1. Java核心技术及面试指南 多线程并发部分的面试题总结以及答案

    7.2.10.1有T1.T2.T3三个线程,如何保证T2在T1执行完后执行,T3在T2执行完后执行? 用join语句,在t3开始前join t2,在t2开始前join t1. 不过,这会破坏多线程的并 ...

  2. Java核心技术及面试指南 键值对方面的面试题总结以及答案

    3.3.5.1如何遍历HashMap对象?尤其请说明通过Iterator遍历HashMap对象的方法. 建议用这种方式: Set<Entry<String,String>>en ...

  3. Java核心技术及面试指南 流程控制方面的面试题答案

    2.2.5.1 switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 1 switch里可以用char,byte,short,int这些基本类型,以及它们的封装类.  ...

  4. Java核心技术及面试指南 集合部分总的面试题归纳以及答案

    3.6.1ArrayList和LinkedList有什么差别?在哪种场景里应当用ArrayList(或LinkedList)? 大家如果学过数据结构,这个问题不难回答:前者是基于数组,数组比较擅长索引 ...

  5. Java核心技术及面试指南:视频列表

    如下是本书相关内容的视频列表,会动态更新 第一章 1 视频1.1  JDK和JRE和JVM的区别,安装Java开发环境    1.1.1  第2页 2 视频1.2  编写第一个HelloWorld程序 ...

  6. Java核心技术及面试指南 JDBC部分的面试题总结以及答案

    5.5.1 你最近的项目里用到的是哪个数据?或你用过哪些数据库?或你对哪个数据库最熟悉? 通过这个问题,我们将会确认候选人是否在项目里用过数据库或JDBC. 5.5.2 你有没有建过表?或修改表里的字 ...

  7. Java核心技术及面试指南 数据库方面的面试题归纳以及总结

    5.1.7.1 事务的四大特性是什么? ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚. ⑵ 一致性(Consistency) 一致性是指事务必须使数据库 ...

  8. Java核心技术及面试指南的视频讲解和代码下载位置

    都是百度云盘,均无密码 代码下载位置: https://pan.baidu.com/s/1I44ob0vygMxvmj2BoNioAQ 视频讲解位置: https://pan.baidu.com/s/ ...

  9. Java核心技术及面试指南 设计模式部分的面试题总结以及答案

    8.6.4.1请实现一个线程安全的单例模式. 1      public class MailListReader { 2          private static MailListReader ...

随机推荐

  1. java Quartz任务调度器

    1.quarz对java1.5实现的简单调度做了封装 /**     * quartz对任务调度进了高度抽象: 1调度器:2任务:3触发器     * Job接口(任务):定义需要调度的任务     ...

  2. 《Linux就该这么学》第十一天课程

     防火墙常用的一些命令参数 原创地址:https://www.linuxprobe.com/chapter-08.html firewalld中常用的区域名称及策略规则 区域 默认规则策略 trust ...

  3. C语言内存四区的学习总结(一)---- 静态区

    最近重新学习C语言相关知识,重新提到内存四区的概念,那么在之前的学习的基础上,在这儿做一个简单的总结与分享. 一.内存四区建立的流程 可以简单直观的查看下面的这个图片,直接的说明我们的程序在内存中是如 ...

  4. php获取指定日期,前一天、前一周、前一个月、前一年,后一天,后一周,前一个月,前一年

    dump( date( 'Y-m-d', strtotime('2018-10-1 +1 day') ) ); dump( date( 'Y-m-d', strtotime('2018-10-1 +1 ...

  5. fortran语言调用fortran写的dll

    环境:vs2013+IVF 2011 有时候想把fortran写的常用的函数编译为DLL,以供不同的fortran exe调用,这时候应该怎样做呢?[参考 彭国伦老师 fortran95 程序设计 书 ...

  6. maven 不能使用 snapshot 的解决方式

    最近项目需要用到snapshot的包来进行构建过程,但是怎么都下不了构建的snapshot包.查询了相关资料,发现网上的资料不全,特总结下: 我使用的是nexus来作为代理中央库proxy. 检查步骤 ...

  7. windows安装zookeeper

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...

  8. win10更新永久关闭

    最烦开发的时候windows来个更新 http://www.ghost580.com/win10/2016-10-21/17295.html

  9. 记录做一个类似于探探的卡片式布局的Recycleview有数据一直不显示

    使用了别人的项目 https://github.com/JerryChan123/ReSwipeCard/blob/master/README_zh.md 之前找recycleview有数据不显示的原 ...

  10. 如何在已安装Python解释器的Linux上更新Python

    在Linux环境下升级Python (附:解决pip报错 subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned ...