java借助NIO、链表、跳表模拟实现redis

LinkItem.java:链表的一个元素

java 复制代码
package com.qixian.general.entity;

public class LinkItem {

    public String key;
    public long keyascii=0;
    public void getAsciiCode() {
        String keyasciiStr="";
        for(int i=0;i<key.length();i++){
            keyasciiStr=keyasciiStr+(int)key.charAt(i);
        }
        keyascii = Long.parseLong(keyasciiStr);
    }

    public LinkItem previous;
    public LinkItem next;
    public Object data;
}

LinkSkip.java :跳表的上部类似索引的部分

java 复制代码
package com.qixian.general.entity;

public class LinkSkip {

    public String key;
    public long keyascii=0;

    public LinkSkip previous;
    public LinkSkip next;
    public LinkItem current;
    public LinkSkip currentSkip;
}

MyHashMap.java:自己用java模拟的哈希结构,数据存储为跳表结构

java 复制代码
package com.qixian.general.study;

public class MyHashMap {


    int[] index={0,1,2,3,4,5,6,7,8,9};

    SkipList skipList0=new SkipList();
    SkipList skipList1=new SkipList();
    SkipList skipList2=new SkipList();
    SkipList skipList3=new SkipList();
    SkipList skipList4=new SkipList();
    SkipList skipList5=new SkipList();
    SkipList skipList6=new SkipList();
    SkipList skipList7=new SkipList();
    SkipList skipList8=new SkipList();
    SkipList skipList9=new SkipList();


    public Object get(String key){

        String keyasciiStr="";
        for(int i=0;i<key.length();i++){
            keyasciiStr=keyasciiStr+(int)key.charAt(i);
        }
        long keyascii = Long.parseLong(keyasciiStr);
        long index =dividekey(keyascii);
        Object data = null;
        switch ((int) index){
            case 0:
                data=skipList0.getData(key);
                break;
            case 1:
                data=skipList1.getData(key);
                break;
            case 2:
                data=skipList2.getData(key);
                break;
            case 3:
                data=skipList3.getData(key);
                break;
            case 4:
                data=skipList4.getData(key);
                break;
            case 5:
                data=skipList5.getData(key);
                break;
            case 6:
                data=skipList6.getData(key);
                break;
            case 7:
                data=skipList7.getData(key);
                break;
            case 8:
                data=skipList8.getData(key);
                break;
            case 9:
                data=skipList9.getData(key);
                break;
            default:
                break;
        }

        return data;
    }


    public void put(String key,Object value){

        String keyasciiStr="";
        for(int i=0;i<key.length();i++){
            keyasciiStr=keyasciiStr+(int)key.charAt(i);
        }
        long keyascii = Long.parseLong(keyasciiStr);
        long index =dividekey(keyascii);
        switch ((int) index){
            case 0:
                skipList0.addLinkItem(key,value);
                break;
            case 1:
                skipList1.addLinkItem(key,value);
                break;
            case 2:
                skipList2.addLinkItem(key,value);
                break;
            case 3:
                skipList3.addLinkItem(key,value);
                break;
            case 4:
                skipList4.addLinkItem(key,value);
                break;
            case 5:
                skipList5.addLinkItem(key,value);
                break;
            case 6:
                skipList6.addLinkItem(key,value);
                break;
            case 7:
                skipList7.addLinkItem(key,value);
                break;
            case 8:
                skipList8.addLinkItem(key,value);
                break;
            case 9:
                skipList9.addLinkItem(key,value);
                break;
            default:
                break;
        }
    }

    long dividekey(long keyascii){
        keyascii=keyascii/2;
        if(keyascii>9){
            return dividekey(keyascii);
        }else {
            return keyascii;
        }
    }



    public static void main(String[] args) {
        SkipList list=new SkipList();
        list.addLinkItem("qiang","{name:wlq,sex:男}");
        list.addLinkItem("qiang2","{name:wlq2,sex:男}");
        list.addLinkItem("qiang3","{name:wlq3,sex:男}");
        list.addLinkItem("qiang4","{name:wlq4,sex:男}");
        list.addLinkItem("qiang5","{name:wlq5,sex:男}");
        list.addLinkItem("qiang6","{name:wlq6,sex:男}");
        list.addLinkItem("qiang7","{name:wlq7,sex:男}");
        list.addLinkItem("qiang8","{name:wlq8,sex:男}");
        list.addLinkItem("qiang9","{name:wlq9,sex:男}");
        list.addLinkItem("qiang10","{name:wlq10,sex:男}");
        list.addLinkItem("qiang11","{name:wlq11,sex:男}");
        list.addLinkItem("qiang12","{name:wlq12,sex:男}");
        list.addLinkItem("qiang13","{name:wlq13,sex:男}");
        list.addLinkItem("qiang14","{name:wlq14,sex:男}");
        list.addLinkItem("qiang15","{name:wlq15,sex:男}");
        list.addLinkItem("qiang16","{name:wlq16,sex:男}");
        Object qiang3 = list.getData("qiang10");
        System.out.println(qiang3.toString());


    }
}

SkipList.java :一个跳表类型

java 复制代码
package com.qixian.general.study;

import com.qixian.general.entity.LinkItem;
import com.qixian.general.entity.LinkSkip;

public class SkipList {

    public LinkItem firstLinkItem;

    public LinkSkip rootSkipItem;

    public Object getData(String key){

        long keyascii=0;
        String keyasciiStr="";
        for(int i=0;i<key.length();i++){
            keyasciiStr=keyasciiStr+(int)key.charAt(i);
        }
        keyascii = Long.parseLong(keyasciiStr);

        Boolean advance=true;
        LinkSkip root=rootSkipItem;
        LinkItem target;
        while (true){
            if(advance){

                if(root.keyascii<keyascii){
                    if(root.next!=null){
                        root=root.next;
                    }else {
                        root=root.currentSkip;
                    }
                }else {
                    if(root.currentSkip==null){

                        target=root.current;
                        advance=false;
                        break;
                    }else {
                        root=root.currentSkip;
                        advance=false;
                    }
                }
            }else {

                if(root.keyascii>keyascii){
                    if(root.previous!=null){
                        root=root.previous;
                    }else {
                        root=root.currentSkip;
                    }
                }else {
                    if(root.currentSkip==null){
                        target=root.current;
                        advance=true;
                        break;

                    }else {
                        root=root.currentSkip;
                        advance=true;
                    }
                }
            }
        }

            while (true){
                if(target.keyascii==keyascii){
                    break;
                }else {
                    if(advance) {
                        target=target.next;
                    }else {
                        target=target.previous;
                    }
                }
            }

            return target.data;
    }

    public void generateSkip(){
        if(firstLinkItem!=null){
            rootSkipItem=new LinkSkip();
            rootSkipItem.current=firstLinkItem;
            rootSkipItem.keyascii=firstLinkItem.keyascii;
            if(firstLinkItem.next!=null){

                generate(rootSkipItem,firstLinkItem.next,0);
            }
            while (countLinkSkip()>=3){
                LinkSkip newRootSkipItem=new LinkSkip();
                newRootSkipItem.currentSkip=rootSkipItem;
                newRootSkipItem.keyascii=rootSkipItem.keyascii;
                generateSkipItem(newRootSkipItem,rootSkipItem.next,0);
                rootSkipItem=newRootSkipItem;
            }
        }
    }
    public int countLinkSkip(){
        int count=0;
        LinkSkip current=rootSkipItem;
        while (true){
            count++;
            if(current.next==null){
                break;
            }else {
                current=current.next;
            }
        }
        return count;
    }

    public void generateSkipItem(LinkSkip linkSkipCurrent,LinkSkip linkSkipLowCurrent,int interim){
        LinkSkip item=null;
        if(interim==1){
            item=new LinkSkip();
            item.keyascii=linkSkipLowCurrent.keyascii;
            item.currentSkip=linkSkipLowCurrent;
        }
        if(item==null){
            item=linkSkipCurrent;
        }else {
            linkSkipCurrent.next=item;
            item.previous=linkSkipCurrent;
        }
        interim=interim==0?1:0;
        if(linkSkipLowCurrent.next!=null){
            generateSkipItem(item,linkSkipLowCurrent.next,interim);
        }

    }
    public void generate(LinkSkip linkSkipCurrent,LinkItem linkItemCurrent,int interim){
        LinkSkip item=null;
        if(interim==1){
            item=new LinkSkip();
            item.keyascii=linkItemCurrent.keyascii;
            item.current=linkItemCurrent;
        }
        if(item==null){
            item=linkSkipCurrent;
        }else {
            linkSkipCurrent.next=item;
            item.previous=linkSkipCurrent;
        }
        interim=interim==0?1:0;
        if(linkItemCurrent.next!=null){
            generate(item,linkItemCurrent.next,interim);
        }

    }
    public void addLinkItem(String key,Object data){
        LinkItem linkItem=new LinkItem();
        linkItem.key=key;
        linkItem.data=data;
        linkItem.getAsciiCode();
        if(firstLinkItem==null){
            firstLinkItem=linkItem;
        }else {
            addLinkItem(firstLinkItem,linkItem);
        }
        generateSkip();
    }
    private void addLinkItem(LinkItem linkItemCurrent,LinkItem linkItem){
        if(linkItemCurrent.keyascii<linkItem.keyascii){
            if(linkItemCurrent.next!=null){
                addLinkItem(linkItemCurrent.next,linkItem);
            }else {
                linkItemCurrent.next=linkItem;
            }
        }else {
            if(linkItemCurrent.previous!=null){
                linkItemCurrent.previous.next=linkItem;
                linkItem.previous=linkItemCurrent.previous;
            }
            linkItem.next=linkItemCurrent;
            linkItemCurrent.previous=linkItem;
        }
    }


}

MyRedis.java:借助NIO实现单线程可以并发响应网络连接请求,并单线程操作hash表存放和查询数据,此处的hash是redis全局大hash,key值唯一,数据类型可以是字符串,链表(队列,栈)等

java 复制代码
package com.qixian.general.study;

import com.qixian.general.entity.LinkItem;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

public class MyRedis {
    public static int[] index={0,1,2,3,4,5,6,7,8,9};

    static LinkItem myRedisHashMap0=null;
    static LinkItem myRedisHashMap1=null;
    static LinkItem myRedisHashMap2=null;
    static LinkItem myRedisHashMap3=null;
    static LinkItem myRedisHashMap4=null;
    static LinkItem myRedisHashMap5=null;
    static LinkItem myRedisHashMap6=null;
    static LinkItem myRedisHashMap7=null;
    static LinkItem myRedisHashMap8=null;
    static LinkItem myRedisHashMap9=null;

    public static void main(String[] args) throws IOException, InterruptedException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8899));
        serverSocketChannel.configureBlocking(false);
        Selector selector = Selector.open();
        SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            selector.select();
            Set<SelectionKey> selectionKeySet = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeySet.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = server.accept();

                    socketChannel.configureBlocking(false);
                    SelectionKey selKey = socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();

                    ByteBuffer byteBuffer = ByteBuffer.allocate(128);
                    int len = socketChannel.read(byteBuffer);

                    if (len > 0) {
                        Date date = new Date();
                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
                        System.out.println(dateFormat.format(date) + "收到了来自于客户端" +
                                socketChannel.socket().getInetAddress().getHostName()
                                + "的消息:" + new String(byteBuffer.array()));
                        String content= new String(byteBuffer.array());
                        String[] split = content.split(" ");
                        if(split[0].equals("SET")){
                            String key1=split[1];
                            String value1=split[2];

                            String keyasciiStr="";
                            for(int i=0;i<key1.length();i++){
                                keyasciiStr=keyasciiStr+(int)key1.charAt(i);
                            }
                            long keyascii = Long.parseLong(keyasciiStr);
                            long index =dividekey(keyascii);
                            LinkItem linkItem = new LinkItem();
                            linkItem.key=key1;
                            linkItem.keyascii=keyascii;
                            value1=value1.replace("\0","");
                            linkItem.data=value1;
                            switch ((int) index){
                                case 0:
                                    myRedisHashMap0=addLinkItem(linkItem,myRedisHashMap0);
                                    break;
                                case 1:
                                    myRedisHashMap1=addLinkItem(linkItem,myRedisHashMap1);
                                    break;
                                case 2:
                                    myRedisHashMap2=addLinkItem(linkItem,myRedisHashMap2);
                                    break;
                                case 3:
                                    myRedisHashMap3=addLinkItem(linkItem,myRedisHashMap3);
                                    break;
                                case 4:
                                    myRedisHashMap4=addLinkItem(linkItem,myRedisHashMap4);
                                    break;
                                case 5:
                                    myRedisHashMap5=addLinkItem(linkItem,myRedisHashMap5);
                                    break;
                                case 6:
                                    myRedisHashMap6=addLinkItem(linkItem,myRedisHashMap6);
                                    break;
                                case 7:
                                    myRedisHashMap7=addLinkItem(linkItem,myRedisHashMap7);
                                    break;
                                case 8:
                                    myRedisHashMap8=addLinkItem(linkItem,myRedisHashMap8);
                                    break;
                                case 9:
                                    myRedisHashMap9=addLinkItem(linkItem,myRedisHashMap9);
                                    break;
                                default:
                                    break;
                            }
                        }
                        if(split[0].equals("GET")){
                            String key1=split[1];
                            key1=key1.replace("\0","");
                            String keyasciiStr="";
                            for(int i=0;i<key1.length();i++){
                                keyasciiStr=keyasciiStr+(int)key1.charAt(i);
                            }
                            long keyascii = Long.parseLong(keyasciiStr);
                            long index =dividekey(keyascii);
                            LinkItem result=null;
                            LinkItem current=null;
                            switch ((int) index){
                                case 0:
                                    result =getListItem(keyascii,myRedisHashMap0);
                                    break;
                                case 1:
                                    result =getListItem(keyascii,myRedisHashMap1);
                                    break;
                                case 2:
                                    result =getListItem(keyascii,myRedisHashMap2);
                                    break;
                                case 3:
                                    result =getListItem(keyascii,myRedisHashMap3);
                                    break;
                                case 4:
                                    result =getListItem(keyascii,myRedisHashMap4);
                                    break;
                                case 5:
                                    result =getListItem(keyascii,myRedisHashMap5);
                                    break;
                                case 6:
                                    result =getListItem(keyascii,myRedisHashMap6);
                                    break;
                                case 7:
                                    result =getListItem(keyascii,myRedisHashMap7);
                                    break;
                                case 8:
                                    result =getListItem(keyascii,myRedisHashMap8);
                                    break;
                                case 9:
                                    result =getListItem(keyascii,myRedisHashMap9);
                                    break;
                                default:
                                    break;
                            }
                            if(result!=null){
                                System.out.println("查询数据:"+result.data.toString());

                                ByteBuffer wrap = ByteBuffer.wrap(result.data.toString().getBytes(StandardCharsets.UTF_8));
                                socketChannel.write(wrap);
                            }

                        }

                    } else if (len == -1) {
                        socketChannel.close();
                        System.out.println("客户端断开");
                    }
                }
                iterator.remove();
            }
        }
    }

    static LinkItem getListItem(long keyascii,LinkItem current){

        while (true){
            if(current.keyascii==keyascii){
                return current;
            }else {
                if(current.next!=null){
                    current=current.next;
                }else {
                    return null;
                }
            }
        }
    }
    static LinkItem addLinkItem(LinkItem linkItem,LinkItem previous){

        LinkItem root=null;
        if(previous==null){
            root=linkItem;
            return root;
        }else {
            while (true){
                if(linkItem.keyascii<previous.keyascii){
                    if(previous.previous==null){
                        myRedisHashMap0=linkItem;
                        linkItem.next=previous;
                    }else {
                        linkItem.previous=previous.previous;
                        linkItem.next=previous;
                        previous.previous.next=linkItem;
                        previous.previous=linkItem;

                    }
                    break;
                }else {
                    if(previous.next==null){
                        previous.next=linkItem;
                        break;
                    }else {
                        previous=previous.next;
                    }
                }
            }
            return previous;
        }
    }

    static long dividekey(long keyascii){
        keyascii=keyascii/2;
        if(keyascii>9){
            return dividekey(keyascii);
        }else {
            return keyascii;
        }
    }


//    public static void main(String[] args) {
//
//        MyHashMap myHashMap=new MyHashMap();
//        myHashMap.put("qiang","{name:wlq,sex:男}");
//        myHashMap.put("qiang2","{name:wlq2,sex:男}");
//        myHashMap.put("qiang3","{name:wlq3,sex:男}");
//        myHashMap.put("qiang4","{name:wlq4,sex:男}");
//        myHashMap.put("qiang5","{name:wlq5,sex:男}");
//        myHashMap.put("qiang6","{name:wlq6,sex:男}");
//        myHashMap.put("qiang7","{name:wlq7,sex:男}");
//        myHashMap.put("qiang8","{name:wlq8,sex:男}");
//        myHashMap.put("qiang9","{name:wlq9,sex:男}");
//        myHashMap.put("qiang10","{name:wlq10,sex:男}");
//        myHashMap.put("qiang11","{name:wlq11,sex:男}");
//        myHashMap.put("qiang12","{name:wlq12,sex:男}");
//        myHashMap.put("qiang13","{name:wlq13,sex:男}");
//        myHashMap.put("qiang14","{name:wlq14,sex:男}");
//        myHashMap.put("qiang15","{name:wlq15,sex:男}");
//        myHashMap.put("qiang16","{name:wlq16,sex:男}");
//        Object qiang3 = myHashMap.get("qiang10");
//        System.out.println(qiang3.toString());
//    }
}

测试类:先发送100个存储命令,在发送一个查询命令

java 复制代码
package com.tjcloud.uac.facade;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Study1 {
//    public static void main(String[] args) {
//        //socket对象初始化
//        Socket socket = null;
//
//        //输出流 os对象初始化
//        OutputStream os = null;
//        try {
//
//            //1、创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
//            InetAddress inet = InetAddress.getByName("127.0.0.1");
//            socket = new Socket(inet,8899);//inet是服务端ip
//
//            //2、获取一个输出流,用于写出要发送的数据
//            os = socket.getOutputStream();
//
//            for (int i = 0;i<100;i++){
//
//                //3、写出数据
//                os.write(("SET wlq"+i+" {name:wlq"+i+",sex:男}").getBytes());
//                os.flush();
//                Thread.sleep(500);
//            }
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        } finally {
//            //4、释放资源,别忘了哦!!!!
//            if(socket!=null){
//                try {
//                    socket.close();//关闭
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//            if(os!=null){
//                try {
//                    os.close();//关闭
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//    }



    public static void main(String[] args) {
        //socket对象初始化
        Socket socket = null;

        //输出流 os对象初始化
        OutputStream os = null;
        try {

            //1、创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
            InetAddress inet = InetAddress.getByName("127.0.0.1");
            socket = new Socket(inet,8899);//inet是服务端ip

            //2、获取一个输出流,用于写出要发送的数据
            os = socket.getOutputStream();

            os.write(("GET wlq"+15).getBytes());
            os.flush();
            Thread.sleep(500);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            //4、释放资源,别忘了哦!!!!
            if(socket!=null){
                try {
                    socket.close();//关闭
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(os!=null){
                try {
                    os.close();//关闭
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
//


}
相关推荐
.生产的驴几秒前
SpringBoot 接口国际化i18n 多语言返回 中英文切换 全球化 语言切换
java·开发语言·spring boot·后端·前端框架
Howard_Stark4 分钟前
Spring的BeanFactory和FactoryBean的区别
java·后端·spring
饮长安千年月5 分钟前
学生管理系统审计
java·网络安全·代码审计
-曾牛13 分钟前
Spring Boot中@RequestParam、@RequestBody、@PathVariable的区别与使用
java·spring boot·后端·intellij-idea·注解·spring boot 注解·混淆用法
新时代苦力工25 分钟前
处理对象集合,输出Map<String, Map<String, List<MyObject>>>格式数据,无序组合键处理方法
java·数据结构·list
niesiyuan00039 分钟前
MAC如何安装多版本jdk(以8,11,17为例)
java
zcyf08091 小时前
kafka理论学习汇总
java·分布式·学习·kafka
再拼一次吧1 小时前
Spring进阶篇
java·后端·spring
爱编程的小庄1 小时前
Maven 4.0.0 模式-pom.xml配置详解
xml·java·maven
黄雪超1 小时前
JVM——引入
java·jvm