java集合框架增强

集合框架图

集合框架

List接口三个实现类

  • ArrayList:底层由数组实现,线程不安全,效率高;所以随机访问快,修改、插入、删除慢
  • LinkedList:底层由链表实现,线程不安全,效率高;所以查询慢,修改,插入,删除快
  • Vector:线程安全,效率低

自己实现ArrayList类

/**
 * 自己实现一个简单的ArrayList,帮助我们更好的理解ArrayList类的底层结构
 * @author L J
 *
 */
public class LArrayList {
    //存储元素[核心数组]
    private Object[] elementData;

    //代表容器大小
    private int size;

    //获取容器大小
    public int size() {
        return size;
    }

    //容器是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    public LArrayList() {
        this(10);
    }

    public LArrayList(int initialCapacity) {
        if(initialCapacity < 0) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        elementData = new Object[initialCapacity];
    }

    //范围检查
    private void rangeCheck(int index) {
        if(index < 0 || index >= size) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //扩容
    private void ensureCapacity() {
        //数组扩容
        if(size >= elementData.length) {
            Object[] newArray = new Object[(size + 1) * 2];
            //数组拷贝
            //System.arraycopy(elementData, 0, newArray, 0, elementData.length);

            for(int i = 0; i < elementData.length; i++) {
                newArray[i] = elementData[i];
            }

            elementData = newArray;
        }
    }

    //添加元素
    public void add(Object obj) {
        ensureCapacity();
        elementData[size++] = obj;
        //size++;
    }

    public void add(int index, Object obj) {
        rangeCheck(index);
        ensureCapacity();

        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = obj;
        size++;
    }

    //获取元素
    public Object get(int index) {
        rangeCheck(index);
        return elementData[index];
    }

    //从容器中移除指定位置的元素
    public void remove(int index) {
        rangeCheck(index);
        //需要向前移动的元素的个数
        int numMoved = size - index - 1;

        if(numMoved > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);
        }

        //最后一个元素变为空
        elementData[--size] = null;
    }

    //删除一个指定元素
    public void remove(Object obj) {
        for(int i = 0; i < size; i++) {
            if(get(i).equals(obj)) {  //底层调用equals方法,而非==
                remove(i); 
            }
        }
    }

    //在指定的索引位置更新一个元素
    public Object set(int index, Object obj) {
        rangeCheck(index);
        Object oldValue = elementData[index];
        elementData[index] = obj;
        return oldValue;
    }
}

自己实现LinkedList类

/**
 * 自己实现一个LinkedList类
 * @author L J
 */
public class LLinkedList {
    //头节点
    private Node first;

    //尾节点
    private Node last;

    //表示容器的大小
    private int size;

    //获取容器大小
    public int size() {
        return size;
    }

    //添加一个元素
    public void add(Object obj) {
        Node n = null;
        if(first == null) {
            n = new Node();
            n.setPrevious(null); //头节点始终是null
            n.setObj(obj);
            n.setNext(null);     //还没有下一个节点

            //创建的第一个节点,即是头节点,也是尾节点
            first = n;
            last = n; 
        }else{
            //直接往last节点后增加新的节点
            n = new Node();
            n.setPrevious(last);
            n.setObj(obj);
            n.setNext(null);

            //当前节点指向新创建的节点
            last.setNext(n);

            //当前最后一个节点是新创建的节点
            last = n;
        }
        size++;
    }

    //范围检查
    private void rangeCheck(int index) {
        if(index < 0 || index >= size) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //获取对应索引位置的一个元素
    public Object get(int index) {
        rangeCheck(index);
        Node temp = node(index);
        if(temp != null) {
            return temp.obj;
        }
        return null;
    }

    //遍历找到对应位置的节点
    public Node node(int index) {
        Node temp = null;
        if(first != null) {
            //分别从前后遍历链表,提高效率
            if(index < (size >> 1)) {
                temp = first;
                for(int i = 0; i < index; i++) {
                    temp = temp.next;
                }
            }else{
                temp = last;
                for(int i = size - 1; i > index; i--) {
                     temp = temp.previous;
                }
            }
        }
        return temp;
    }

    //移除一个元素
    public void remove(int index) {
        rangeCheck(index);
        Node temp = node(index);
        if (temp != null) {
            Node up = temp.previous;
            Node down = temp.next;

            //移除首尾元素时会抛出空指针异常,看源码解决
            up.next = down;
            down.previous = up;
            size--;
        }
    }

    //在指定位置插入一个元素
    public void add(int index, Object obj) {
        rangeCheck(index);

        //创建新节点
        Node newNode = new Node();
        newNode.obj = obj;

        Node temp = node(index);
        if(temp != null) {
            Node up = temp.previous;
            //对头节点操作的时候也会抛出空指针异常
            up.next = newNode;
            newNode.previous = up;

            newNode.next = temp;
            temp.previous = newNode;

            size++;
        }
    }
}

自定义Map

/**
 * 自己实现一个Map类,效率较低
 * @author L J
 */
public class LMap {
    //此类重在理解Map,所以数组扩容等忽略
    LEntry[] arr = new LEntry[999];
    //表示容器大小
    int size;
    //获取容器大小
    public int size() {
        return size;
    }

    //向Map中添加一个元素
    public void put(Object key, Object value) {
        LEntry e = new LEntry(key, value);

        //键不能重复[键相同,就用新值覆盖旧值]
        for(int i = 0; i < size; i++) {
            if(arr[i].key.equals(key)) {
                arr[i].value = value;
                return;
            }
        }
        arr[size++] = e;
    }

    //通过key获取一个元素
    public Object get(Object key) {
        for(int i = 0; i < size; i++) {
            if(arr[i].key.equals(key)) {
                return arr[i].value;
            }
        }
        return null;
    }

    //检测是否包含key
    public boolean containsKey(Object key) {
        for(int i = 0; i < size; i++) {
            if(arr[i].key.equals(key)) {
                return true;
            }
        }
        return false;
    }

    //检测是否包含value
    public boolean containsValue(Object value) {
        for(int i = 0; i < size; i++) {
            if(arr[i].value.equals(value)) {
                return true;
            }
        }
        return false;
    }
}

//entry是条目的意思[键值对]
class LEntry {
    Object key;
    Object value;

    public LEntry(Object key, Object value) {
        super();
        this.key = key;
        this.value = value;
    }
}

升级版Map

/**
 * 自定义Map升级版
 * @author L J
 */
public class LMap01 {
    //map的底层结构,数组+链表,数组中存储链表
    LinkedList[] arr = new LinkedList[999];

    //容器大小
    int size;

    //获取容器大小
    public int size() {
        return size;
    }

    //向Map中添加一个元素
    public void put(Object key, Object value) {
        LEntry e = new LEntry(key, value);

        int hash = key.hashCode();
        hash = hash < 0 ? -hash : hash;
        int a = hash % arr.length;

        if(arr[a] == null) {
            //创建一个链表
            LinkedList list = new LinkedList();
            arr[a] = list;

            //将键值对存入链表
            list.add(e);
        }else{
            //取得链表
            LinkedList list = arr[a];
            //key相同,覆盖value
            for(int i = 0; i < list.size(); i++) {
                LEntry e1 = (LEntry) list.get(i);
                if(e1.key.equals(key)) {
                    e1.value = value;
                }
            }
            arr[a].add(e);
        }
        size++;
    }

    //通过key获取一个元素
    public Object get(Object key) {
        int hash = key.hashCode();
        hash = hash < 0 ? -hash : hash;
        int a = hash % arr.length;

        if(arr[a] != null) {
            //取得链表
            LinkedList list = arr[a];
            //遍历找出key对应的value
            for(int i = 0; i < list.size(); i++) {
                LEntry e = (LEntry) list.get(i);
                if(e.key.equals(key)) {
                    return e.value;
                }
            }
        }
        return null;
    }
}

equals和hashCode

java中规定,两个内容相同的对象,应该具有相同的hashCode;重写equals方法必须重写hashCode方法

//重写equals和hashCode方法
public class Student {
    private int id;
    private String name;
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        //散列
        result = prime * result + id;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (id != other.id)
            return false;
        return true;
    }
}

自定义HashSet类

/**
 * 自定义HashSet类
 * @author L J
 */
public class LHashSet {
    //Set的底层实现是Map
    HashMap map;

    private static final Object PRESENT = new Object();

    //表示容器的大小
    int size;

    //构造器
    public LHashSet() {
        map = new HashMap();
    }

    //获取容器的大小
    public int size() {
        return map.size();
    }

    //向Set中添加元素
    public void add(Object o) {
        //Set不可重复就是利用了Map中键不可重复这一特点
        map.put(o, PRESENT);  
    }
}

遍历Map的两种方式

    @Test
    public void testMap1() {
        Map<Integer,String> map = new HashMap<Integer, String>();
        map.put(100, "jack");    //key = 100  value = "jack"
        map.put(200, "marry");
        map.put(300, "sisi");
        Set<Integer> set = map.keySet();//只获取key值,将map转换为set
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()) {
            Integer key = it.next();
            String value = map.get(key);
            System.out.println(key + "-" + value);
        }
    }
    @Test
    public void testMap2() {
        Map<Integer,String> map = new HashMap<Integer, String>();
        map.put(100, "jack");   
        map.put(200, "marry");
        map.put(300, "sisi");
        Set<Entry<Integer, String>> set = map.entrySet();//entry中存储的是记录<key,value>
        Iterator<Entry<Integer, String>> it= set.iterator();
        while(it.hasNext()) {
            Entry<Integer, String> entry = it.next();
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "<->" + value);
        }
    }
}

Map迭代

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值