自定义Java集合

一、泛型

1、在JDK1.4以前,所有的集合元素全都按照Object来存储,拿出来还要进行强制转型。由于这样的做法有太多的缺点,容易出现ClassCaseException,不安全,让人不省心,于是乎JDK5之后出现了泛型。

2、什么是泛型,通俗的讲,就是在Java文件编译期对类型进行检查。比如:List<String> string = new ArrayList<String>(); 它只能装String类型的对象,否则编译时报错。

二、自定义ArrayList

1、ArrayList顾名思义,底层就是使用数组实现的List。

2、代码

package com.collection.arrayList;

import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
//实现Iterable接口,就可以使用forEach
public class MyArrayList<E> implements Iterable<E> {
    //Object的数组,Java没有泛型数组
    private Object[] elementData = null;
    private int size = 0;
      //默认的数组大小是10
    public MyArrayList() {
        this(10);

    }
    public MyArrayList(int cacaptiy) {
        elementData = new Object[cacaptiy];
    }

    public boolean add(E obj) {
        //如果当前元素个数已经跟数组一样大了,就扩容
        if(size >= elementData.length) {
            this.ensureCapacityInternal(elementData.length);

        }
        elementData[size++] = obj;

        return true;
    }

    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] arr) {

        if(arr.length < size) {

            return (T[]) Arrays.copyOf(elementData, size, arr.getClass());
        }
        System.arraycopy(elementData, 0, arr, 0, arr.length);
        if(arr.length > size) {
            arr[size] = null;

        }

        return arr;
    }

    @SuppressWarnings("unchecked")
    public E[] toArray() {

            return (E[]) Arrays.copyOf(elementData, elementData.length);
        }

    public boolean addAll(MyArrayList<E> list) {

        for(int i = 0; i < list.size; i++) {
            this.add(list.get(i));
        }

            return true;
    }

    public boolean set(int index, E obj) {
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        ensureCapacityInternal(1);
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = obj;
        size ++;
        return true;

    }

    public boolean remove(int index) {
        if(index < 0 || index >= size) {

            throw new ArrayIndexOutOfBoundsException();

        }
        System.arraycopy(elementData, index + 1, elementData, index, size - index -1);
        size --;
        return true;

    }

    public boolean remove(E obj) {

        for(int i = 0; i < elementData.length; i++) {
            if(obj == elementData[i]) {
                System.arraycopy(elementData, i + 1, elementData, i, size - i - 1);
                size --;
                return true;
            } else if(obj.equals(elementData[i]) && obj.hashCode() == elementData[i].hashCode()) {

                System.arraycopy(elementData, i + 1, elementData, i, size - i - 1);
                size --;
                return true;
            }

        }

        return false;

    }

    @SuppressWarnings("unchecked")
    public E get(int index) {
        if(index < 0 || index >= size) {

                throw new ArrayIndexOutOfBoundsException();

        }
        return (E) elementData[index];

    }

    public void ensureCapacityInternal(int cacaptiy) {
        Object[] newArr = new Object[elementData.length + cacaptiy];
        System.arraycopy(elementData, 0, newArr, 0, elementData.length);
        elementData = newArr;
    }

    public int size() {

        return size;
    }

    public boolean isEmpty() {

        return size == 0;

    }

    public void clear() {

        for(int i = 0; i <size; i++) {
            elementData[i] = null;
        }
        size = 0;
    }

    public Iterator<E> iterator() {

        return new Itr();
    }

    private class Itr implements Iterator<E>{
        private int cursor = 0;
        private int lastRet = -1;

        @Override
        public boolean hasNext() {
            return cursor != size();
        }

        @SuppressWarnings("unchecked")
        @Override
        public E next() {
            if(cursor == size()) {
                throw new NoSuchElementException();

            }
            lastRet = cursor;
            return (E) elementData[cursor ++];
        }

        public void remove() {
            if(lastRet == -1) {
                throw new IllegalStateException();
            }
            MyArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;

        }

    }

}

三、自定义LinkedList

1、LinkedList底层是用链表实现的

2、先定义一个Node类

package com.collection.linkedList;

public class Node {
    //前一个节点的引用
    private Node prev;
    //存储的数据
    private Object object;
    //下一个节点的引用
    private Node next;

    public Node getPrev() {
        return prev;
    }

    public void setPrev(Node prev) {
        this.prev = prev;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

}

3、MyLinkedList.java

package com.collection.linkedList;

public class MyLinkedList<E> {

    private Node header;//链表的节点头

    private Node tail;//链表的结尾

    private int size;//记录当前元素的大小

    public MyLinkedList() {

    }
    /**
     * 在某个位置插入元素
     * @param index
     * @param obj
     */
    public void set(int index, E obj) {
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        Node node = new Node();
        node.setObject(obj);
        Node temp1 = header;
        Node temp = null;
        Node temp2 = tail;
        Node prev = null;
        //除以,看看这个index离header近还是tail近
        if(index >= (size >> 1)) {

            for(int i = 0; i < index; i++) {
                temp1 = temp1.getNext();
            }
            temp = temp1;
        } else {
            for(int i = 0; i < size - index - 1; i++) {
                temp2 = temp2.getPrev();
            }
            temp = temp2;
        }
        prev = temp.getPrev();
        if(prev != null) {

            prev.setNext(node);

        } else {
            header = node;
        }
        node.setNext(temp);
        temp.setPrev(node);
        size ++;
    }

    public boolean remove(int index) {
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }

        Node temp = header;

        for(int i = 0; i < index; i++) {
            temp = temp.getNext();

        }
        Node prev = temp.getPrev();
        Node next = temp.getNext();
        if(prev != null) {

            prev.setNext(next);
        } else {

            header = next;
        }
        if(next != null) {

            next.setPrev(prev);
        } else {

            tail = prev;
        }
        size --;
        return true;

    }

    public boolean remove(Object obj) {
        if(obj == null) {

            return false;
        }
        Node temp = header;
        Node prev = null;
        Node next = null;

        while(temp != null) {
            if(temp.getObject() == obj) {

                prev = temp.getPrev();
                next = temp.getNext();
                if(prev != null) {

                    prev.setNext(next);
                } else {
                    header = next;

                }
                if(next != null) {

                    next.setPrev(prev);
                } else {
                    tail = prev;
                }
                size --;
                return true;

            } else if(temp.getObject().equals(obj) && obj.hashCode() == temp.getObject().hashCode()) {

                prev = temp.getPrev();
                next = temp.getNext();
                if(prev != null) {

                    prev.setNext(next);
                } else {

                    header = next;
                }
                if(next != null) {

                    next.setPrev(prev);
                } else {
                    tail = prev;
                }
                size --;
                return true;
            }
            temp = temp.getNext();
        }

        return false;

    }

    public boolean add(E obj) {
        Node node = new Node();
        node.setObject(obj);
        if(header == null) {
            header = node;
            header.setPrev(null);
            tail = node;
            node.setNext(null);

        } else {
            node.setPrev(tail);
            tail.setNext(node);
            tail = node;
            node.setNext(null);

        }
        size ++;
        return true;
    }

    @SuppressWarnings("unchecked")
    public E get(int index) {
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }

        Node temp = header;

        for(int i = 0; i < index; i++) {
            temp = temp.getNext();

        }

        return (E) temp.getObject();
    }

    public int size() {

        return size;
    }

}

四、自定义HashMap

1、HashMap的底层是用数组和链表实现的,数组的元素是链表,链表里存的是键值对对象

2、键值对类MyEntry.java

package com.collection.hashMap;

public class MyEntry {

    private Object key;//键

    private Object value;//值

    public MyEntry(Object key, Object value) {
        this.key = key;
        this.value = value;

    }

    public Object getKey() {
        return key;
    }

    public void setKey(Object key) {
        this.key = key;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

}

3、MyHashMap.java

package com.collection.hashMap;

import java.util.LinkedList;

/**
 * hashmap是由数组和链表一起构成的
 * 由于使用的是hashCode,顺序不能保证,它是无顺序的。
 * @author may
 *
 * @param <E>
 * @param <U>
 */
public class MyHashMap<E, U> {

    private Object[] elementData = null;

    private int size;

    private int cacaptiy = 10;

    public MyHashMap() {

        elementData = new Object[cacaptiy];
    }

    @SuppressWarnings("unchecked")
    public boolean put(E key, U value) {
        int hashCode = Math.abs(key.hashCode());
        MyEntry entry = new MyEntry(key, value);
        LinkedList<MyEntry> linkedList = (LinkedList<MyEntry>) elementData[hashCode % cacaptiy];
        //key的hashCode可能会重复,需要做判断
        if(linkedList != null) {
            boolean flag = false;
            for(int i = 0; i < linkedList.size(); i++) {
                if(linkedList.get(i).getKey().equals(key)) {

                    linkedList.get(i).setValue(value);
                    flag = true;//return;
                    break;
                }
            }
            if(!flag) {

                linkedList.add(entry);
                size ++;
            }

        } else {
            linkedList = new LinkedList<MyEntry>();
            linkedList.add(entry);
            if(size == cacaptiy) {
                esureCacaptiy(cacaptiy);
            }
            elementData[hashCode % cacaptiy] = linkedList;
            size ++;
        }

        return true;
    }

    public void esureCacaptiy(int increment) {
        Object[] obj = new Object[cacaptiy + increment];
        cacaptiy = cacaptiy + increment;
        System.arraycopy(elementData, 0, obj, 0, elementData.length);
        elementData = obj;
    }

    @SuppressWarnings("unchecked")
    public U get(E key) {
        int hashCode = key.hashCode();
        LinkedList<MyEntry> linkedList = (LinkedList<MyEntry>) elementData[hashCode % cacaptiy];
        if(linkedList != null) {

            for(int i = 0; i < linkedList.size(); i++) {
                if(linkedList.get(i).getKey().equals(key)) {

                    return (U) linkedList.get(i).getValue();

                }

            }

        }

        return null;

    }

    public int size() {

        return size;
    }

}

五、自定义HashSet

1、HashSet的底层用的是HashMap,它保存的值就是HashMap里的key

2、代码

package com.collection.hashSet;

import java.util.HashMap;

/**
 * HashSet底层是用HashMap实现的,是无序的
 * @author may
 *
 * @param <K>
 */
public class MyHashSet<K> {

    private HashMap<K, Object> map = null;

    //map的值是固定的
    private final static Object PRESENT = new Object();

    public boolean add(K obj) {
        map.put(obj, PRESENT);
        return true;

    }

    public boolean remove(K obj) {
        map.remove(obj);

        return true;
    }

}
时间: 2024-10-26 21:40:19

自定义Java集合的相关文章

Java集合框架实现自定义排序

Java集合框架针对不同的数据结构提供了多种排序的方法,虽然很多时候我们可以自己实现排序,比如数组等,但是灵活的使用JDK提供的排序方法,可以提高开发效率,而且通常JDK的实现要比自己造的轮子性能更优化. 一 .使用Arrays对数组进行排序 Java API对Arrays类的说明是:此类包含用来操作数组(比如排序和搜索)的各种方法. 1.使用Arrays排序:Arrays使用非常简单,直接调用sort()即可 int[] arr = new int[] {5,8,-2,0,10}; Array

Java集合相关面试问题和答案

Java集合相关面试问题和答案 面试试题 1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector.Stack.HashTable和Array.随着集合的广泛使用,Java1.2提出了囊括所有集合接口.实现和算法的集合框架.在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久.它还包括在Java并发包中,阻塞接口以及它们的实现.集合框架的部分优点如下: (1)使用核心集合类降低开发成本,而非实现我们自己的集合类.

40个Java集合面试问题和答案

一.基础知识 Java集合框架 1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector.Stack.HashTable和Array. 随着集合的广泛使用,Java1.2提出了囊括所有集合接口.实现和算法的集合框架.在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久.它还包括在Java并发包中,阻塞接口以及它们的实现. 集合框架的部分优点如下: (1)使用核心集合类降低开发成本,而非实现我们自己的集合类. (2)

java集合框架22

思想:在面向对象的思想里,一种数据结构被认为是一种容器.在本质上来讲是一个类,提供方法支持查找,插入和删除等等操作. Java集合框架支持以下俩种类型的容器: 存储一个元素集合,简称为集合Collection 存储键值对,称为图Map 集合collection 三种主要类型 : 规则集(set) , 线型表(List) , 队列(Queue) set: 存储一组不重复的数据 List: 存储由元素构成的有序集合 Queue: 存储先进先出方式处理的对象 细说Collection接口: 它是处理对

疯狂Java学习笔记(61)-----------40个Java集合面试问题和答案

1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector.Stack.HashTable和Array.随着集合的广泛使用,Java1.2提出了囊括所有集合接口.实现和算法的集合框架.在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久.它还包括在Java并发包中,阻塞接口以及它们的实现.集合框架的部分优点如下: (1)使用核心集合类降低开发成本,而非实现我们自己的集合类. (2)随着使用经过严格测试的集合框架类,代

java集合排序问题

List: 元素是有序的,元素可以重复,因为该集合体系有索引(脚标) 常用的子类对象: 1----ArrayList 底层的数据结构是使用的数组结构特点:查询速度快,但是增删比较慢 2----LinkedList底层的数据结构使用的是链表结构特点:增删速度快,但是查询比较慢 Vector 底层是数组数据结构. 线程同步,ArrayList线程不同步,替代了vector ArrayList 是可变长度数组,默认长度是10,当添加的元素大于10时,系统自动new一个新的数组且增长原数组的一半长度,并

Java集合框架总结(5)——Map接口的使用

Java集合框架总结(5)--Map接口的使用 Map用于保存具有映射关系的数据(key-vlaue).Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false Map中包含了一个keySet()方法,用于返回Map所以key组成的Set集合. Map集合与Set集合元素的存储形式很像,如Set接口下有HashSet.LinkedHashSet.SortedSet(接口).TreeSet.EnumSet等实现类和子接口,而Map接口下则有HashMa

[转载]Java集合框架的常见面试题

http://www.jfox.info/40-ge-java-ji-he-lei-mian-shi-ti-he-da-an 整理自上面链接: Java集合框架为Java编程语言的基础,也是Java面试中很重要的一个知识点.这里,我列出了一些关于Java集合的重要问题和答案. 1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector.Stack.HashTable和Array.随着集合的广泛使用, Java1.2提出了囊括所有集

java集合学习一

1.Set存放的元素是无序的不可重复. 2.List存放的元素为有序可重复. 3.重写equals方法,一般最好重写hasCode方法,当对象作为key的时候及索引,会使用hasCode方法进行查找. 4.容器对象在调用remove,contains等方法时需要比较对象是否相等,这会涉及到对象类型的equals方法和 hashCode方法.对于自定义的类型,需要重写equals和hashCode方法以实现自定义的对象相等规则.相等的对象 应该具有相等的hashCode. 5.ArrayList底