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();
}
}
}
}
//
}