/*

  使用接口+抽象类+具体类实现

  ArrayList实现原理:添加元素时要判断ArrayList中是否还有多余空间,若没有 则创建大小是当前数组两倍的新数组, 然后在复制原来的数组到新数组中

  LinkList实现原理:利用结点(node),当向链表中加入一个新的元素时,就会产生一个包含它的结点 类似与c++使用指针实现

*/

package wangChaoPA实习工作练习.com.进阶篇.线性表;

/**
 *
 * <p>
 * 描述该类情况 {@link 代表跟谁有关系}
 * </p>
 *
 * @author 王超
 * @since 1.0
 * @date 2017年5月11日 下午1:51:03
 * @see 新建|修改|放弃
 * @see wangChaoPA实习工作练习.com.进阶篇.线性表.MyList
 */
// 接口中默认的方法都是 public abstract 类型 变量都是 public static final 类型
public interface MyList<E>
{
    // 添加
    void add(E e);

// 指定位置添加
    void add(int index, E e);

// 清空列表
    void clear();

// 是否包含元素e
    boolean contains(E e);

// 通过索引获取元素
    E get(int index);

// 从链表 表头 向表尾 遍历 返回第一个与e相等的元素的索引 若没有相同的元素返回-1
    int indexOf(E e);

// 链表是否为空
    boolean isEmpty();

// 从链表 表尾 向表头 遍历 返回第一个与e相等的元素的索引 若没有相同的元素返回-1
    int lastIndexOf(E e);

// 删除链表中 元素e,并返回删除是否成功
    boolean remove(E e);

// 删除链表中 index索引的元素,并返回
    E remove(int index);

// 在指定下标处放置元素并返回该元素
    Object set(int index, E e);

// 链表大小
    int size();
}
//


//抽象类 实现类接口个别方法

package wangChaoPA实习工作练习.com.进阶篇.线性表;
public abstract class MyAbstractList<E> implements MyList<E>
{
    // 链表长度
    protected int size = 0;

// 默认构造方法
    MyAbstractList()
    {
    }

// 带参的构造方法
    MyAbstractList(E[] objects)
    {
        for (int i = 0; i < objects.length; i++)
        {
            add(objects[i]);
        }
    }

@Override
    public void add(E e)
    {
        add(this.size, e);
    }

@Override
    public boolean isEmpty()
    {
        return this.size == 0;
    }

@Override
    public boolean remove(E e)
    {
        if (indexOf(e) >= 0)
        {
            remove(indexOf(e));
            return true;
        }
        return false;
    }

@Override
    public int size()
    {
        return this.size;
    }

}


//ArrayList实现类

package wangChaoPA实习工作练习.com.进阶篇.线性表;
public class MyArrayList<E> extends MyAbstractList<E>
{
    // 初始长度
    public static final int INITIAL_CAPACITY = 16;

// 泛型不能直接使用new 关键字创建数组
    private E[] data = (E[]) new Object[INITIAL_CAPACITY];

// 默认构造方法
    public MyArrayList()
    {
    }

// 带参的构造方法
    public MyArrayList(E[] objects)
    {
        for (int i = 0; i < objects.length; i++)
        {
            add(objects[i]);
        }
    }

@Override
    public void add(int index, E e)
    {
        ensureCapacity();
        // index以后的元素 后移一位
        for (int i = this.size - 1; i >= index; i--)
        {
            this.data[i + 1] = this.data[i];
        }
        // 插入e
        this.data[index] = e;
        // 链表长度加1
        this.size++;
    }

@Override
    public void clear()
    {
        // 新的data链表
        this.data = (E[]) new Object[INITIAL_CAPACITY];
        // 长度为0
        this.size = 0;
    }

@Override
    public boolean contains(E e)
    {
        for (int i = 0; i < this.size; i++)
        {
            if (e.equals(data[i]))
            {
                return true;
            }
        }
        return false;
    }

// 如果需要就将当前数组的大小加倍
    private void ensureCapacity()
    {
        if (this.size >= this.data.length)
        {
            E[] newData = (E[]) (new Object[size * 2 + 1]);
            System.arraycopy(this.data, 0, newData, 0, this.size);
            this.data = newData;
        }
    }

@Override
    public E get(int index)
    {
        return this.data[index];
    }

@Override
    public int indexOf(E e)
    {
        for (int i = 0; i < this.size; i++)
        {
            if (e.equals(this.data[i]))
            {
                return i;
            }
        }
        return -1;
    }

@Override
    public int lastIndexOf(E e)
    {
        for (int i = size - 1; i >= 0; i--)
        {
            if (e.equals(this.data[i]))
            {
                return i;
            }
        }
        return -1;
    }

@Override
    public E remove(int index)
    {
        E temp = this.data[index];
        if (index >= this.size)
        {
            return null;
        }
        else
        {
            for (int i = index; i < this.size; i++)
            {
                this.data[i] = this.data[i + 1];
            }
            // 删除最后一个元素
            this.data[this.size - 1] = null;
            this.size--;
        }
        return temp;
    }

@Override
    public Object set(int index, E e)
    {
        E oddObject = this.data[index];
        if (index >= this.size)
        {
            return null;
        }
        else
        {
            this.data[index] = e;
            return oddObject;
        }
    }

// 当一个Object实例被转化成String时,Java就会自动调用toString()方法返回一个String。
    // System.out.println标准输出,只能输出String,所以,所有需要输出的Object都会被转化成String。
    // 如果你没有覆盖toString,那么,Java会自动调用最上层父类Object的toString()方法。
    @Override
    public String toString()
    {
        StringBuilder result = new StringBuilder("[");
        for (int i = 0; i < size; i++)
        {
            result.append(data[i]);
            if (i < size - 1)
            {
                result.append(", ");
            }
        }
        return result.toString() + "]";
    }

public void trimToSize()
    {
        if (this.size != this.data.length)
        {
            E[] newData = (E[]) (new Object[size]);
            System.arraycopy(this.data, 0, newData, 0, size);
            this.data = newData;
        }
    }
}


//LinkList的实现类
package wangChaoPA实习工作练习.com.进阶篇.线性表;

public class MyLinkList<E> extends MyAbstractList<E>
{
    // 头结点,尾结点
    private Node<E> head, tail;

// 默认构造方法
    public MyLinkList()
    {
    }

// 带参的构造方法
    public MyLinkList(E[] objects)
    {
        super(objects);
    }

@Override
    public void add(int index, E e)
    {
        if (index == 0)
        {
            addFirst(e);
        }
        else if (index >= this.size)
        {
            addLast(e);
        }
        else
        {
            Node<E> current = this.head;
            // 找到需要添加元素位置的前一个结点
            for (int i = 1; i < index; i++)
            {
                current = current.next;
            }
            // e插入到current与temp之间
            Node<E> temp = current.next;
            current.next = new Node<E>(e);
            current.next.next = temp;
            this.size++;
        }
    }

// 元素添加到头结点
    public void addFirst(E e)
    {
        Node<E> newNode = new Node<E>(e);
        // newNode的next指向head
        newNode.next = this.head;
        // newNode成为head
        this.head = newNode;
        // 大小加1
        this.size++;
        // 当链表中没有结点时
        if (this.tail == null)
        {
            this.tail = this.head;
        }
    }

// 元素添加到尾结点
    public void addLast(E e)
    {
        Node<E> newNode = new Node<E>(e);
        // 当链表中没有结点时
        if (this.tail == null)
        {
            this.tail = this.head = newNode;
        }
        else
        {
            // tail与newNode建立联系
            this.tail.next = newNode;
            // tail指向最后的结点
            this.tail = this.tail.next;
        }
        // 大小加1
        this.size++;
    }

// 清空链表
    @Override
    public void clear()
    {
        this.head = this.tail = null;
    }

// 是否包含e
    @Override
    public boolean contains(E e)
    {
        Node<E> current = this.head;
        for (int i = 0; i < this.size - 1; i++)
        {
            if (e.equals(current.element))
            {
                return true;
            }
            current = current.next;
        }
        return false;
    }

@Override
    public E get(int index)
    {
        if (index < 0 || index >= this.size)
        {
            return null;
        }
        else
        {
            Node<E> current = this.head;
            for (int i = 0; i < index; i++)
            {
                current = current.next;
            }
            return current.element;
        }
    }

// 返回头结点的值
    public E getFirst()
    {
        if (this.size == 0)
        {
            return null;
        }
        else
        {
            return this.head.element;
        }
    }

// 返回尾结点的值
    public E getLast()
    {
        if (this.size == 0)
        {
            return null;
        }
        else
        {
            return this.tail.element;
        }
    }

// 从表头向表尾遍历 如有和e相同的element则返回其索引值 否则返回-1
    @Override
    public int indexOf(E e)
    {
        Node<E> current = this.head;
        for (int i = 0; i < this.size - 1; i++)
        {
            if (e.equals(current.element))
            {
                return i;
            }
            current = current.next;
        }
        return -1;
    }

// 暂时没有实现 无法从后到先遍历?????
    @Override
    public int lastIndexOf(E e)
    {
        Node<E> current = this.tail;
        for (int i = this.size - 1; i >= 0; i--)
        {
            if (e.equals(current.element))
            {
                return i;
                // current=current.next;
            }
        }
        return -1;
    }

@Override
    public E remove(int index)
    {
        if (index < 0 || index >= this.size)
        {
            return null;
        }
        else if (index == 0)
        {
            return removeFirst();
        }
        else if (index == this.size - 1)
        {
            return removeLast();
        }
        else
        {
            Node<E> previous = this.head;
            for (int i = 1; i < index; i++)
            {
                previous = previous.next;
            }
            // current 就是要删除的结点
            Node<E> current = previous.next;
            previous.next = current.next;
            this.size--;
            return current.element;
        }
    }

// 删除头结点 并返回头结点中的element
    public E removeFirst()
    {
        if (this.size == 0)
        {
            return null;
        }
        else if (this.size == 1)
        {
            Node<E> temp = this.head;
            this.head = this.tail = null;
            this.size = 0;
            return temp.element;
        }
        else
        {
            Node<E> newHead = this.head.next;
            E ele = this.head.element;
            this.head = newHead;
            this.size--;
            return ele;
        }
    }

// 删除尾结点 并返回尾结点中的element
    public E removeLast()
    {
        if (this.size == 0)
        {
            return null;
        }
        else if (this.size == 1)
        {
            Node<E> temp = this.head;
            this.head = this.tail = null;
            this.size = 0;
            return temp.element;
        }
        else
        {
            Node<E> current = this.head;
            for (int i = 0; i < this.size - 2; i++)
            {
                current = current.next;
            }
            Node<E> temp = this.tail;
            this.tail = current;
            this.tail.next = null;
            this.size--;
            return temp.element;
        }
    }

@Override
    public Object set(int index, E e)
    {
        if (index < 0)
        {
            return null;
        }
        else if (index == 0)
        {
            return getFirst();
        }
        else if (index == this.size - 1)
        {
            return getLast();
        }
        else
        {
            Node<E> current = this.head;
            for (int i = 1; i < index; i++)
            {
                current = current.next;
            }
            Node<E> temp = current.next;
            Node<E> newNode = new Node<E>(e);
            current.next = newNode;
            newNode.next = temp.next;
            return temp.element;
        }
    }

@Override
    public String toString()
    {
        StringBuilder result = new StringBuilder("[");
        Node<E> current = this.head;
        for (int i = 0; i < this.size; i++)
        {
            result.append(current.element);
            current = current.next;
            if (current != null)
            {
                result.append(", ");
            }
            else
            {
                result.append("]");
            }
        }
        return result.toString();
    }
}

// 结点类
class Node<E>
{
    E element;
    Node<E> next;

public Node(E e)
    {
        this.element = e;
    }
}

转载于:https://www.cnblogs.com/qingtianBKY/p/6841019.html

java ArrayListLinkList相关推荐

  1. java面试必背知识点

    JAVA必背面试题和项目面试通关要点 一 数据库 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链接查询和优化问题,手写SQL语句,例如四个球队比赛,用SQL显示所有比赛组合:举例2:选 ...

  2. JAVA必背面试题和项目面试通关要点

    一 数据库 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链接查询和优化问题,手写SQL语句,例如四个球队比赛,用SQL显示所有比赛组合:举例2:选择重复项,然后去掉重复项:) 数据库里 ...

  3. springboot实现SSE服务端主动向客户端推送数据,java服务端向客户端推送数据,kotlin模拟客户端向服务端推送数据

    SSE服务端推送 服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE).本文介绍它的用法. 在很多业务场景中,会涉及到服务端向客户端 ...

  4. Java 获取当前时间之后的第一个周几,java获取当前日期的下一个周几

    Java 获取当前时间之后的第一个周几,java获取当前日期的下一个周几 //获得入参的日期 Calendar cd = Calendar.getInstance(); cd.setTime(date ...

  5. 在k8s中使用gradle构建java web项目镜像Dockerfile

    在k8s中使用gradle构建java web项目镜像Dockerfile FROM gradle:6-jdk8 AS build COPY --chown=gradle:gradle . /home ...

  6. Java | kotlin 手动注入bean,解决lateinit property loginService has not been initialized异常

    kotlin.UninitializedPropertyAccessException: lateinit property loginService has not been initialized ...

  7. SpringBoot项目使用nacos,kotlin使用nacos,java项目使用nacos,gradle项目使用nacos,maven项目使用nacos

    SpringBoot项目使用nacos kotlin demo见Gitte 一.引入依赖 提示:这里推荐使用2.2.3版本,springboot与nacos的依赖需要版本相同,否则会报错. maven ...

  8. OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3

    OpenAPI使用(swagger3) demo见Gitte 一.背景及名词解释 OpenAPI是规范的正式名称.规范的开发工作于2015年启动,当时SmartBear(负责Swagger工具开发的公 ...

  9. Gradle错误提示:Java home supplied via ‘xxx.xxx.xxx‘ is invalid

    Gradle错误提示:Java home supplied via 'org.gradle.java.home' is invalid 描述:在使用idea采用gradle进行依赖的管理功能,当想切换 ...

  10. 查看Hotspot源码,查看java各个版本源码的网站,如何查看jdk源码

    java开发必知必会之看源码,而看源码的第一步则是找到源码

最新文章

  1. Windows安装MRTG后的配置
  2. ROP简单 ret2syscall
  3. 了解 Apache ActiveMQ
  4. PyTorch-torch.nn.AdaptiveAvgPool2d
  5. Asp.Net Core之Identity应用(下篇)
  6. ODPS2.0重装上阵,优化提升SQL语言表达能力
  7. JFinalConfig
  8. 求最大子数组(贪心算法)
  9. 【AIX】AIX 开机自动挂载NFS共享
  10. 【毕业设计】JAVA文件压缩与解压缩实践(源代码+论文)
  11. Pikachu实验过程重现(Burp suit的具体介绍)
  12. 12-畅通工程续(多种方法求最短路径)
  13. 入侵检测——masscan(扫描篇)
  14. Apache2 Linux 的安装与介绍
  15. Python中form的使用
  16. 834 计算机专业基础综合参考书,2018年上海大学834计算机科学专业基础综合考研复习资料...
  17. oracle中文转换为unicode,oracle 用函数unistr将Oracle数据库中的Unicode转换为中文
  18. 计算组合数的几种方法总结
  19. java取当前周期、月初至月末、季度初至季度末日期
  20. 解决异常: SSL peer shut down incorrectly原因

热门文章

  1. 从头开始学Android之(一)——— Android架构
  2. 继续ajax长轮询解决方案--递归
  3. 小强的HTML5移动开发之路(32)—— JavaScript回顾7
  4. (转)Android 如何建立你的菜单
  5. HDOJ2005 ( 第几天? ) 【水题】
  6. c#操作Xml(五)
  7. CCIE试验备考之交换security
  8. oracle 外部os授权,外部OS认证的过程
  9. html中展开的小箭头,HTML5 移动网页应用中的展开式标签(带上下指示箭头)
  10. Unity的序列化机制探索