IDEA显示 参数快捷键 HASHMAP底层源码手写

本文展示了如何手写快速排序算法对用户实体类中的年龄进行排序,并实现了一个简单的哈希映射类,使用数组加链表的方式。通过实验比较了在不同数据规模下,数组和链表的查找效率。实验结果显示,对于大规模数据,链表的查找速度相对较慢,而快速排序在处理数据排序时具有较高的效率。
摘要由CSDN通过智能技术生成

CTRL+P

手写一个排序 快排排序 用户实体类中的年龄

package org.example;

import java.util.ArrayList;
import java.util.List;

/**
 * 對象排序
 * List Userinfos 規定按照用戶的年齡進行排序 從高到低
 * fanxing泛型
 */
//泛型类 在构建本类对象时就告知该对象中的这个泛型是什么类型 建造对象时临时指定泛型类型
public class MyObjectSort {
    static List<Userinfos> uss = new ArrayList<Userinfos>();
    static{
        uss.add(new Userinfos(1,"zs",20));
        uss.add(new Userinfos(2,"ls",18));
        uss.add(new Userinfos(3,"ww",44));
        uss.add(new Userinfos(4,"zl",32));
        uss.add(new Userinfos(5,"sq",55));
        uss.add(new Userinfos(6,"wb",70));
    }

    public void quick(int low,int high) {
        int lo=low,hi=high;
        if ( lo >= hi ) {
            return;
        }
        boolean flag = false;
        while ( lo < hi ) {
            if ( uss.get(lo).compareTo(uss.get(hi)) == 0) {
                Userinfos temp = uss.get(lo);
                uss.set(lo,uss.get(hi));
                uss.set(hi,temp);

                flag=!flag;
            }
            if (flag)
                lo++;
            else
                hi--;
        }
        lo--;hi++;
        quick(low,lo);
        quick(hi,high);
    }

    public static void main(String[] args) {
        MyObjectSort mos = new MyObjectSort();
        mos.quick(0,5);
        System.out.println(mos);
    }
}

 

package org.example;

public class Userinfos implements Comparable<Userinfos>{
    private int userid;
    private String username;
    private int age;

    @Override
    public int compareTo(Userinfos o) {
        if ( this.age > o.getAge() ) {
            return 1;
        } else {
            return 0;
        }
    }

    public Userinfos() {
    }

    public Userinfos(int userid, String username, int age) {
        this.userid = userid;
        this.username = username;
        this.age = age;
    }

    public int getUserid() {
        return userid;
    }

    public void setUserid(int userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

手写一个 hashmap底层源码 以及一些方法 

使用的是数组加链表 JDK1.7以前的方法

package org.example;

public class MyMap<K,V> {
    transient int size;//你的Map中所有元素的个数
    private static final int DEFAULT_CAPACITY=1<<4;//hash表默认容量
    private static final int DEFAULT_THRESHOLD=1<<3;//默认阈值
    transient Node<K,V> [] table;

    public MyMap(){
        table = new Node[DEFAULT_CAPACITY];
    }

    public void put(K key,V value) {
        //计算hash值
        int hash = hash(key);
        //根据hash值找到数据应该存放的位置求余
        int pos = hash%table.length;
        //到数组中查看该位置是否已经有数据链表如果有就遍历链表 如果链表中已经有该数据则 替换对应的值 否则把数据添加到链表的尾部
        if( table[pos] == null ) {
            //空的就直接构建1个链表
            Node<K,V> newNode = new Node<K,V>(hash,key,value,null);
            table[pos]=newNode;
            size++;
        }else {
            //如果位置上不空
            //检查用户传入的key是否和链表中的key重复 如果重复就用用户传入的value值替换对应的值
            Node<K,V> x=table[pos];//开始时存放链表头部
            Node<K,V> last = null;//存放链表的尾部
            do {
                if (x.key == key) {
                    //进行数据覆盖
                    x.value = value;
                    break;
                }
                last = x;
            }while( (x=x.next) != null);

            if ( x == null ){
                Node<K,V> newNode = new Node<K,V>(hash,key,value,null);
                last.next = newNode;
                size++;
            }
        }

    }

    /**
     * 查找数据是否存在
     * @param key
     * @return
     */
    public boolean contains(K key) {
        return true;
    }

    private int hash(K key) {
      if ( key == null ) {
          return 0;
      }else {
          int h = key.hashCode();
          return Math.abs(h^(h>>>16));
      }
    }





    private static class Node<K,V> {
        private long hashCode;
        private K key;
        private V value;
        private Node<K,V> next;

        public Node() {
        }

        public Node(long hashCode, K key, V value, Node<K, V> next) {
            this.hashCode = hashCode;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public long getHashCode() {
            return hashCode;
        }

        public void setHashCode(long hashCode) {
            this.hashCode = hashCode;
        }

        public K getKey() {
            return key;
        }

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

        public V getValue() {
            return value;
        }

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

        public Node<K, V> getNext() {
            return next;
        }

        public void setNext(Node<K, V> next) {
            this.next = next;
        }
    }
}


package org.example;

public class MyLink<T> {
    transient int size;//存放元素的个数
    transient Node<T> first;//存放首环地址
    transient Node<T> last;//存放尾环地址
    public MyLink(){}

    /**
     * 把一个元素存放到链表中,通常存放在链表的末尾
     * @param item
     */
    public void add(T item) {
        //建造一个Node对象
        Node<T> newNode = new Node<T>(null,item,null);
        //判断是否是首次添加一环
        if ( first == null && last == null ) {
            //直接将建造的对象存放到first和last中
            first = newNode;
            last = newNode;
        }else {
            //不是首环
            //将尾环的next设置为新环
            last.next = newNode;
            //将新环的prev设置为last环
            newNode.prev = last;
            //再将新环存放到last中
            last = newNode;
        }
        size++;
    }

    /**
     * 移除链表中的一个元素 自己添加
     * @param t
     */
    public void remove(T t) {
        //根据用户传入的元素搜索Node
        Node<T> x = first;
        int i =0;
        for ( ; i < size; i++) {//size :10   .... 下标 9
            if (x.item == t) {
                //如果元素的值等于你需要找的值 那么久退出循环 此时i一定小于size
                break;
            }else {
                //如果元素节点值不等于就把节点换成下个节点
                x = x.next;
            }
        }
        //一直找不到 退出循环时一定是10

        //判断是否找到对应元素 i<size说明找到了对应的元素
        if ( i < size ) {
            if ( x == first ) {
                //判断该节点是否是首环 ,首环只要把下一环的prev设置为空 并将first属性设置为下一环
                first = first.next;
                first.prev = null;
            }else if ( x == last ) {
                //判断节点是否是尾环, 尾环要将上一环的next设置为空 并将last属性设置为上一环
                last = last.prev;
                last.next=null;
            }else {
                //如果是中间环,则把上一环的next设置为当前环的下一环 把下一环的prev设置成当前环的上一环
                x.prev.next=x.next;
                x.next.prev=x.prev;
            }
            size--;
        }
    }

    /**
     * 获取链表中的一个指定位置的元素
     * @param index
     * @return
     */
    public T get(int index) {
        //检查用户用户传入的下标是否合法
        if ( index+1 > size  || index < 0 )
            throw new IndexOutOfBoundsException("下标溢出");
        //根据用户给定的下标如果在链表的前半截 就从头搜索 如果在后半截就 从尾向头搜
        if ( index < (size >> 1 ) ) {
            Node<T> x = first;
            for ( int i = 0 ; i < index; i++ )
                x = x.next;
            return x.item;
        }else {
            Node<T> x = last;
            for ( int i = size-1; i > index; i-- )
                x = x.prev;
            return x.item;
        }
    }

    /**
     * 向头部添加一环
     * @param t
     */
    public void addFirst(T t) {
        Node<T> newFirst = new Node<T>(null,t,null);
        first.prev = newFirst;
        newFirst.next = first;
        first = newFirst;
        size++;
    }

    /**
     * 向链表的尾部加入一环
     * @param t
     */
    public void addLast(T t) {
        add(t);
    }

    /**
     * 根据用户给定的位置 修改元素信息
     * @param index
     * @param element
     */
    public void set(int index,T element){
        //根据元素位置 搜索元素
        Node<T> x = first;
        for ( int i=0; i< index ;i++ ) {
            x=x.next;
        }
        x.item = element;
    }




    //内部类 生成环节点
    private static class Node<T> {
        T item;
        Node<T> prev;
        Node<T> next;

        public Node(Node<T> prev,T item, Node<T> next) {
            this.item = item;
            this.prev = prev;
            this.next = next;
        }
    }

    @Override
    public String toString() {
        String str = "[";
        Node<T> x = first;
        for ( int i=0; i<size ;i++) {
            str+=x.item+",";
            x=x.next;
        }
        str = str.substring(0, str.length()-1)+"]";
        return str;
    }
}

 

package com.myh.testkb;


import java.util.LinkedList;
import java.util.List;

public class Test<T> {
    transient Node <T>first;
    transient Node <T>last;
    transient int size;


    private class Node<T>{
        T item;
        Node<T> next;

        public Node(T item, Node<T> next) {
            this.item = item;
            this.next = next;
        }
    }



    public static void main(String[] args) {
        int t=99999999;
        String a[]=new String[t];
        for (int i = 0; i < a.length; i++) {
            a[i]="asdfg";
        }
        a[a.length-1]="asdf";

        List <String>l1= new LinkedList<>();
        for (int i = 0; i < t; i++) {
            if(i<t-1){
                l1.add("asdfg");
            }else {
                l1.add("asdf");
            }
        }


        long time=System.currentTimeMillis();
        for (int i = 0; i < a.length/2; i++) {
            if(a[i].equals("asdf")){
                break;
            }
        }
        System.out.println("第一个:"+ (System.currentTimeMillis()-time));



        //
        time=System.currentTimeMillis();
        l1.get(t/2-1);

        System.out.println("第二个:"+ (System.currentTimeMillis()-time));








    }
}

亲自实验 比较时间复杂度

我找某个值

分别用 fori 数组一个一个比对,  第二种用链表 用x.next方法一个一个往后找。

最后因为后者要找地址 所以速度要慢于前面的。

数值99999999的时候很吃内存  但确实是 链表速度慢些

换种情况 数值小的时候一百万的时候  就是链表更快了 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值