双端java
Ⅰ 集合java代码如何实现
java集合 Collection为父接口,包括list、set、map等常用。
list:有序,可重复
set:无序,不可重复
map:以键值对方式存在的,键唯一,值唯一
下面列举一些开发中常用的:
1.List相关
List books = new ArrayList();
//向books集合中添加三个元素
books.add(new String("轻量级Java EE企业应用实战"));
books.add(new String("疯狂Java讲义"));
books.add(new String("疯狂Android讲义"));
LinkedList books = new LinkedList();
//将字符串元素加入队列的尾部(双端队列)
books.offer("疯狂Java讲义");
//将一个字符串元素加入栈的顶部(双端队列)
books.push("轻量级Java EE企业应用实战");
2.set相关
HashSet books = new HashSet();
//分别向books集合中添加两个A对象,两个B对象,两个C对象
books.add(new A());
books.add(new A());
LinkedHashSet books = new LinkedHashSet();
books.add("Java");
books.add("LittleHann");
System.out.println(books);
TreeSet nums = new TreeSet();
//向TreeSet中添加四个Integer对象
nums.add(5);
nums.add(2);
nums.add(10);
nums.add(-9);
3.map相关
Map map = new HashMap();
map.put("key1","lisi1");
map.put("key2","lisi2");
map.put("key3","lisi3");
map.put("key4","lisi4");
Hashtable ht = new Hashtable();
ht.put(new A(60000) , "疯狂Java讲义");
ht.put(new A(87563) , "轻量级Java EE企业应用实战");
ht.put(new A(1232) , new B());
LinkedHashMap scores = new LinkedHashMap();
scores.put("语文" , 80);
scores.put("英文" , 82);
scores.put("数学" , 76);
TreeMap tm = new TreeMap();
tm.put(new R(3) , "轻量级Java EE企业应用实战");
tm.put(new R(-5) , "疯狂Java讲义");
tm.put(new R(9) , "疯狂Android讲义");
WeakHashMap whm = new WeakHashMap();
whm.put(new String("语文") , new String("良好"));
whm.put(new String("数学") , new String("及格"));
whm.put(new String("英文") , new String("中等"));
Ⅱ 在Java中如何实现双向链表
双向链表:就是有双向指针,即双向的链域。
链结点的结构:
┌────┬────┬────────┐
│ data │ next │ previous │
└────┴────┴────────┘
双向链表不必是双端链表(持有对最后一个链结点的引用),双端链表插入时是双向的。
有两条链:一条从头到尾,一条从尾到头,删除遍历时也是双向的。
/**
* 双向链表
*/
public class DoublyLinkedList<t> {
private Link<t> head; //首结点
private Link<t> rear; //尾部指针
public DoublyLinkedList() { }
public T peekHead() {
if (head != null) {
return head.data;
}
return null;
}
public boolean isEmpty() {
return head == null;
}
public void insertFirst(T data) {// 插入 到 链头
Link<t> newLink = new Link<t>(data);
if (isEmpty()) {//为空时,第1次插入的新结点为尾结点
rear = newLink;
} else {
head.previous = newLink; //旧头结点的上结点等于新结点
}
newLink.next = head; //新结点的下结点旧头结点
head = newLink; //赋值后,头结点的下结点是旧头结点,上结点null
}
public void insertLast(T data) {//在链尾 插入
Link<t> newLink = new Link<t>(data);
if (isEmpty()) {
head = newLink;
} else {
rear.next = newLink;
}
newLink.previous = rear;
rear = newLink; //赋值后,尾结点的上结点是旧尾结点,下结点null
}
public T deleteHead() {//删除 链头
if (isEmpty()) return null;
Link<t> temp = head;
head = head.next; //变更首结点,为下一结点
if (head != null) {
head.previous = null;
} else {
rear = null;
}
return temp.data;
}
public T deleteRear() {//删除 链尾
if (isEmpty()) return null;
Link<t> temp = rear;
rear = rear.previous; //变更尾结点,为上一结点
if (rear != null) {
rear.next = null;
} else {
head = null;
}
return temp.data;
}
public T find(T t) {//从头到尾find
if (isEmpty()) {
return null;
}
Link<t> find = head;
while (find != null) {
if (!find.data.equals(t)) {
find = find.next;
} else {
break;
}
}
if (find == null) {
return null;
}
return find.data;
}
public T delete(T t) {
if (isEmpty()) {
return null;
}
Link<t> current = head;
while (!current.data.equals(t)) {
current = current.next;
if (current == null) {
return null;
}
}
if (current == head) {
head = head.next;
if (head != null) {
head.previous = null;
}
} else if (current == rear) {
rear = rear.previous;
if (rear != null) {
rear.next = null;
}
} else {
//中间的非两端的结点,要移除current
current.next.previous = current.previous;
current.previous.next = current.next;
}
return current.data;
}
public boolean insertAfter(T key, T data) {//插入在key之后, key不存在return false
if (isEmpty()) {
return false;
}
Link<t> current = head;
while (!current.data.equals(key)) {
current = current.next;
if (current == null) {
return false;
}
}
Link<t> newLink = new Link<t>(data);
if (current == rear) {
rear = newLink;
} else {
newLink.next = current.next;
current.next.previous = newLink;
}
current.next = newLink;
newLink.previous = current;
return true;
}
public void displayList4Head() {//从头开始遍历
System.out.println("List (first-->last):");
Link<t> current = head;
while (current != null) {
current.displayLink();
current = current.next;
}
}
public void displayList4Rear() {//从尾开始遍历
System.out.println("List (last-->first):");
Link<t> current = rear;
while (current != null) {
current.displayLink();
current = current.previous;
}
}
class Link<t> {//链结点
T data; //数据域
Link<t> next; //后继指针,结点 链域
Link<t> previous; //前驱指针,结点 链域
Link(T data) {
this.data = data;
}
void displayLink() {
System.out.println("the data is " + data.toString());
}
}
public static void main(String[] args) {
DoublyLinkedList<integer> list = new DoublyLinkedList<integer>();
list.insertLast(1);
list.insertFirst(2);
list.insertLast(3);
list.insertFirst(4);
list.insertLast(5);
list.displayList4Head();
Integer deleteHead = list.deleteHead();
System.out.println("deleteHead:" + deleteHead);
list.displayList4Head();
Integer deleteRear = list.deleteRear();
System.out.println("deleteRear:" + deleteRear);
list.displayList4Rear();
System.out.println("find:" + list.find(6));
System.out.println("find:" + list.find(3));
System.out.println("delete find:" + list.delete(6));
System.out.println("delete find:" + list.delete(1));
list.displayList4Head();
System.out.println("----在指定key后插入----");
list.insertAfter(2, 8);
list.insertAfter(2, 9);
list.insertAfter(9, 10);
list.displayList4Head();
}
}
Ⅲ java双向链表
public boolean putAfter(Object obj,DoublyListNode node)//有可能找不到obj,所以我返回boolean
{
DoublyListNode current = head;
while(head.obj!=obj){
current = current.next;
if(current==null)
return false;
}
if(current==tail){
node.next = null;
tail = node;
}else{
node.next = current.next;
current.next.previous = node;
}
node.previous = current;
current.next =node;
return true;
}
public DoublyListNode removeafter(Object obj){//返回了选中的节点
DoublyListNode current = head;
while(current.obj!=obj)
{
current = current.next;
if(current == null)
return null;
}
if(current==head)
head = current.next;
else
current.previous.next = current.next;
if(current == tail)
tail = current.previous;
else
current.next.previous = current.previous;
return current;
}
Ⅳ java,双端链表
如果为空,第一个创建的结点也是最后一个结点,所以last也指向它。
if(isEmpty())
last=newLink;
如果不为空的话,在表头插入,插入的结点成为第一一个结点,之前的第一结点变为第二结点,有当前新的结点指向
newLink.next=first;
first=newLink;
Ⅳ 通过Java中的Socket技术编写能够进行双向通信的客户端和服务器,为了能够同时进行消息的发送和接受,在服
SocketClient1.java内容如下:
package com.polyphylla.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketClient1 {
private Socket socket;
public SocketClient1() {
try {
socket = new Socket("127.0.0.1", 2222);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
new SocketClient1().startClient();
}
public void startClient() {
new Thread(new ClientReader(socket)).start();
new Thread(new ClientWriter(socket)).start();
}
}
class ClientReader implements Runnable {
private Socket socket;
public ClientReader(Socket socket) {
this.socket = socket;
}
public void run() {
BufferedReader br = getReader();
String msg = null;
try {
while ((msg = br.readLine()) != null) {
System.out.println("client:" + msg);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
if (socket != null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private BufferedReader getReader() {
try {
return new BufferedReader(new InputStreamReader(socket
.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
class ClientWriter implements Runnable {
private Socket socket;
public ClientWriter(Socket socket) {
this.socket = socket;
}
public void run() {
PrintWriter pw = getWriter();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
try {
while ((str = br.readLine()) != null) {
pw.println(str);
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (pw != null)
pw.close();
try {
if (socket != null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private PrintWriter getWriter() {
try {
return new PrintWriter(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
SocketServer1.java内容如下:
package com.polyphylla.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServer1 {
private ServerSocket ss;
public SocketServer1() {
try {
ss = new ServerSocket(2222);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new SocketServer1().startServer();
}
public void startServer() {
try {
while (true) {
Socket s = ss.accept();
new Thread(new ServerReader(s)).start();
new Thread(new ServerWriter(s)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ServerReader implements Runnable {
private Socket socket;
public ServerReader(Socket socket) {
this.socket = socket;
}
public void run() {
BufferedReader br = getReader();
String msg = null;
try {
while((msg = br.readLine()) != null) {
System.out.println("server:" + msg);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(br != null)
br.close();
if(socket != null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private BufferedReader getReader() {
try {
return new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
class ServerWriter implements Runnable {
private Socket socket;
public ServerWriter(Socket socket) {
this.socket = socket;
}
public void run() {
PrintWriter pw = getWriter();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
try {
while((str = br.readLine()) != null) {
pw.println(str);
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (pw != null)
pw.close();
try {
if (socket != null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private PrintWriter getWriter() {
try {
return new PrintWriter(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Ⅵ java中用socket实现客户端与服务端双向连接问题
//服务端程序:
importjava.io.*;
importjava.net.*;
publicclassTCPServer{
publicstaticvoidmain(String[]args)throwsIOException{
newTCPServer().init();
}
@SuppressWarnings("static-access")
privatevoidinit()throwsIOException{
@SuppressWarnings("resource")
ServerSocketserver=newServerSocket(1000);
Socketclient=null;
while(true){
try{
client=server.accept();
BufferedInputStreambis=newBufferedInputStream(client.getInputStream());
byte[]b=newbyte[1024];
intlen=0;
Stringmessage="";
while((len=bis.read(b))!=-1){
message=newString(b,0,len);
System.out.print("客户端:"+client.getInetAddress().getLocalHost().getHostAddress()+"发来消息:"+message);
if("byte".equals(message.trim()))
client.close();
PrintWriterpw=newPrintWriter(client.getOutputStream(),true);
pw.println(message);
}
}catch(Exceptione){
System.err.println("客户端:"+client.getInetAddress().getLocalHost().getHostAddress()+"已断开连接!");
}
}
}
}
//客户端程序:
importjava.io.*;
importjava.net.Socket;
{
publicstaticvoidmain(String[]args)throwsIOException{
newTCPClient().init();
}
privatevoidinit()throwsIOException{
@SuppressWarnings("resource")
finalSocketclient=newSocket("127.0.0.1",1000);
BufferedReaderin=newBufferedReader(newInputStreamReader(System.in));
Stringsend="";
while(true){
send=in.readLine();
PrintWriterout=newPrintWriter(client.getOutputStream(),true);
if(!"byte".equals(send.trim()))
out.println(send);
else{
out.println(send);
System.exit(0);
}
newThread(newTCPClient(){
@SuppressWarnings("static-access")
publicvoidrun(){
try{
BufferedInputStreambis=newBufferedInputStream(client.getInputStream());
byte[]b=newbyte[1024];
intlen=0;
while((len=bis.read(b))!=-1){
System.out.println("服务器:"+client.getInetAddress().getLocalHost().getHostAddress()+"发来消息:"+newString(b,0,len).trim());
}
}catch(IOExceptione){
System.err.println("连接服务器失败!");
}
}
}).start();
}
}
publicvoidrun(){}
}
//服务器测试结果:
客户端:192.168.0.200发来消息:001 byte
客户端:192.168.0.200发来消息:byte
客户端:192.168.0.200 已断开连接!
客户端:192.168.0.200发来消息:adasd
客户端:192.168.0.200 已断开连接!
//客户端测试结果:
---001号客户端--
001byte
服务器:192.168.0.200发来消息:001byte
byte //001礼貌说跟服务器说byte
---002号客户端--
adasd //002客户端直接关闭程序
服务器:192.168.0.200发来消息:adasd
Ⅶ Java:双端队列插入节点,关于队列为空时插入节点的疑问
队列为空的情况下 在首部添加新节点的时候,其实firstNode和lastNode相同都是newNode
,但是无论队列是否为空 方法的最后都会设置firstNode=newNode, 所以为空的时候会设置lastNode=newNode; 在尾部添加新节点的道理也是这样;
Ⅷ java Nio读写为什么是双向
作者:美团技术团队
链接:https://zhuanlan.hu.com/p/23488863
来源:知乎
着作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。
那么NIO的本质是什么样的呢?它是怎样与事件模型结合来解放线程、提高系统吞吐的呢?
本文会从传统的阻塞I/O和线程池模型面临的问题讲起,然后对比几种常见I/O模型,一步步分析NIO怎么利用事件模型处理I/O,解决线程池瓶颈处理海量连接,包括利用面向事件的方式编写服务端/客户端程序。最后延展到一些高级主题,如Reactor与Proactor模型的对比、Selector的唤醒、Buffer的选择等。
注:本文的代码都是伪代码,主要是为了示意,不可用于生产环境。
传统BIO模型分析
让我们先回忆一下传统的服务器端同步阻塞I/O处理(也就是BIO,Blocking I/O)的经典编程模型:
{
ExecutorService executor = Excutors.newFixedThreadPollExecutor(100);//线程池
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(8088);
while(!Thread.currentThread.isInturrupted()){//主线程死循环等待新连接到来
Socket socket = serverSocket.accept();
executor.submit(new ConnectIOnHandler(socket));//为新的连接创建新的线程
}
class ConnectIOnHandler extends Thread{
private Socket socket;
public ConnectIOnHandler(Socket socket){
this.socket = socket;
}
public void run(){
while(!Thread.currentThread.isInturrupted()&&!socket.isClosed()){死循环处理读写事件
String someThing = socket.read()....//读取数据
if(someThing!=null){
......//处理数据
socket.write()....//写数据
}
}
}
}
这是一个经典的每连接每线程的模型,之所以使用多线程,主要原因在于socket.accept()、socket.read()、socket.write()三个主要函数都是同步阻塞的,当一个连接在处理I/O的时候,系统是阻塞的,如果是单线程的话必然就挂死在那里;但CPU是被释放出来的,开启多线程,就可以让CPU去处理更多的事情。其实这也是所有使用多线程的本质:
利用多核。
当I/O阻塞系统,但CPU空闲的时候,可以利用多线程使用CPU资源。
线程的创建和销毁成本很高,在Linux这样的操作系统中,线程本质上就是一个进程。创建和销毁都是重量级的系统函数。
线程本身占用较大内存,像Java的线程栈,一般至少分配512K~1M的空间,如果系统中的线程数过千,恐怕整个JVM的内存都会被吃掉一半。
线程的切换成本是很高的。操作系统发生线程切换的时候,需要保留线程的上下文,然后执行系统调用。如果线程数过高,可能执行线程切换的时间甚至会大于线程执行的时间,这时候带来的表现往往是系统load偏高、CPU sy使用率特别高(超过20%以上),导致系统几乎陷入不可用的状态。
容易造成锯齿状的系统负载。因为系统负载是用活动线程数或CPU核心数,一旦线程数量高但外部网络环境不是很稳定,就很容易造成大量请求的结果同时返回,激活大量阻塞线程从而使系统负载压力过大。
现在的多线程一般都使用线程池,可以让线程的创建和回收成本相对较低。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的I/O并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。
不过,这个模型最本质的问题在于,严重依赖于线程。但线程是很"贵"的资源,主要表现在:
所以,当面对十万甚至百万级连接的时候,传统的BIO模型是无能为力的。随着移动端应用的兴起和各种网络游戏的盛行,百万级长连接日趋普遍,此时,必然需要一种更高效的I/O处理模型。
NIO是怎么工作的
很多刚接触NIO的人,第一眼看到的就是Java相对晦涩的API,比如:Channel,Selector,Socket什么的;然后就是一坨上百行的代码来演示NIO的服务端Demo……瞬间头大有没有?
我们不管这些,抛开现象看本质,先分析下NIO是怎么工作的。
常见I/O模型对比
所有的系统I/O都分为两个阶段:等待就绪和操作。举例来说,读函数,分为等待系统可读和真正的读;同理,写函数分为等待网卡可以写和真正的写。
需要说明的是等待就绪的阻塞是不使用CPU的,是在“空等”;而真正的读写操作的阻塞是使用CPU的,真正在"干活",而且这个过程非常快,属于memory ,带宽通常在1GB/s级别以上,可以理解为基本不耗时。
下图是几种常见I/O模型的对比:
以上都是小编收集了大神的灵药,喜欢的拿走吧!喜欢小编就轻轻关注一下吧!
Ⅸ JAVA怎么实现双向循环链表 如果用LINKEDLIST,我只知道他有hasnext,next方法,那怎么取前一个节点的内容
LinkedList虽然接口是单项的,但内部实现是双向的。
如下方法可以使用:
Iterator<E> descendingIterator() 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
for(Object o : list.descendingIterator()){ ... }
Ⅹ 用JAVA语言,编写一个链表类(双向链表),实现插入,删除,查找操作。新手,要俗易懂些,最好自己调适通过。急
定义接口:
//Deque.java
package dsa; //根据自己的程序位置不同
public interface Deque {
public int getSize();//返回队列中元素数目
public boolean isEmpty();//判断队列是否为空
public Object first() throws ExceptionQueueEmpty;//取首元素(但不删除)
public Object last() throws ExceptionQueueEmpty;//取末元素(但不删除)
public void insertFirst(Object obj);//将新元素作为首元素插入
public void insertLast(Object obj);//将新元素作为末元素插入
public Object removeFirst() throws ExceptionQueueEmpty;//删除首元素
public Object removeLast() throws ExceptionQueueEmpty;//删除末元素
public void Traversal();//遍历
}
双向链表实现:
//Deque_DLNode.java
/*
* 基于双向链表实现双端队列结构
*/
package dsa;
public class Deque_DLNode implements Deque {
protected DLNode header;//指向头节点(哨兵)
protected DLNode trailer;//指向尾节点(哨兵)
protected int size;//队列中元素的数目
//构造函数
public Deque_DLNode() {
header = new DLNode();
trailer = new DLNode();
header.setNext(trailer);
trailer.setPrev(header);
size = 0;
}
//返回队列中元素数目
public int getSize()
{ return size; }
//判断队列是否为空
public boolean isEmpty()
{ return (0 == size) ? true : false; }
//取首元素(但不删除)
public Object first() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
return header.getNext().getElem();
}
//取末元素(但不删除)
public Object last() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
return trailer.getPrev().getElem();
}
//在队列前端插入新节点
public void insertFirst(Object obj) {
DLNode second = header.getNext();
DLNode first = new DLNode(obj, header, second);
second.setPrev(first);
header.setNext(first);
size++;
}
//在队列后端插入新节点
public void insertLast(Object obj) {
DLNode second = trailer.getPrev();
DLNode first = new DLNode(obj, second, trailer);
second.setNext(first);
trailer.setPrev(first);
size++;
}
//删除首节点
public Object removeFirst() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
DLNode first = header.getNext();
DLNode second = first.getNext();
Object obj = first.getElem();
header.setNext(second);
second.setPrev(header);
size--;
return(obj);
}
//删除末节点
public Object removeLast() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
DLNode first = trailer.getPrev();
DLNode second = first.getPrev();
Object obj = first.getElem();
trailer.setPrev(second);
second.setNext(trailer);
size--;
return(obj);
}
//遍历
public void Traversal() {
DLNode p = header.getNext();
while (p != trailer) {
System.out.print(p.getElem()+" ");
p = p.getNext();
}
System.out.println();
}
}