java多线程面试添加学生 用链式结构怎么写

在android开发中显示一个AlertDialog时,常采用下列的写法:
new AlertDialog.Builder(getApplicationContext())
.setTitle("Dialog")
.setMessage("Link program")
.setPositiveButton("OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
可以注意到setTitle/setMessage/setPositiveButton等接口都是直接紧接着执行,用点号隔开,这样的方法叫做链式编程。
观看setTitle,setMessage等源码会发现,每个方法(接口)的返回值都是AlertDialog.Builder类型,所以秘诀在于方法的返回值类型都必须与第一个点号前面的类型保持一致:
* Set the title displayed in the {@link Dialog}.
* @return This Builder object to allow for chaining of calls to set methods
public Builder setTitle(CharSequence title) {
P.mTitle =
return this;
* Set the message to display.
* @return This Builder object to allow for chaining of calls to set methods
public Builder setMessage(CharSequence message) {
P.mMessage =
return this;
这样写法的好处在于一方面可以尽可能少去进行类型转换的判定,而且大大增强了代码的阅读性,同时也减少了代码量。
下面通过一个小例子来演示如何制作这样的链式编程接口
public class LinkProgram {
private String mT
private int mId;
private boolean isA
public static void main(String[] args) {
LinkProgram link = new LinkProgram();
//链式接口调用时,返回值类型和link该对象类型保持一致
link.setAdd(true)
.setText("hello world");
System.out.println(link);
public String toString() {
return "Text:" + mText + ", Id:" + mId + ", add:" + isA
//返回值类型为LinkProgram
public LinkProgram setText(String mText) {
this.mText = mT
return this;
//返回值类型为LinkProgram
public LinkProgram setId(int mId) {
this.mId = mId;
return this;
//返回值类型为LinkProgram
public LinkProgram setAdd(boolean isAdd) {
this.isAdd = isA
return this;
运行结果:Text:hello world, Id:5, add:true
阅读(...) 评论()RxJava的Guihub地址
如果对RxJava还不了解,请先看
多线程处理
为了结果更加的直观,添加RxAndroid的依赖
dependencies {
compile 'io.reactivex:rxjava:1.0.15'
compile 'io.reactivex:rxandroid:1.0.1'
设置运行线程
通过subscribeOn()来指定Observer的运行线程,通过observeOn()指定Subscriber的运行线程。
默认情况下Observer和Subscriber都在当前调用该代码的线程中运行
subscribeOn//Observable被观察者运行的线程
observeOn//Subscriber观察者代码运行的线程
Schedulers.io() //运行至子线程(用于 I/O 操作)
Schedulers.computation() //运行至子线程(计算工作)
Schedulers.newThread() //运行至子线程(为任务创建的新线程)
AndroidSchedulers.mainThread() //运行至主线程 需添加compile ‘io.reactivex:rxandroid:1.0.1’
observable = Observable.create(new Observable.OnSubscribe&String&() {
public void call(Subscriber&? super String& subscriber) {
Log.i(TAG, "create 现在的线程:" + Thread.currentThread().getName());
subscriber.onNext("hello world!");
subscriber.onCompleted();
observable = observable.map(new Func1&String, String&() {
public String call(String s) {
Log.i(TAG, "map 现在的线程:" + Thread.currentThread().getName());
return s + "这是尾巴~";
observable = observable.subscribeOn(Schedulers.io()); //设置Subscriber(观察者)运行在子线程
observable = observable.observeOn(AndroidSchedulers.mainThread()); //设置Observable(被观察者)运行在主线程
Subscriber&String& subscriber = new Subscriber&String&() {
public void onCompleted() {
Log.i(TAG, "onCompleted 现在的线程:" + Thread.currentThread().getName());
public void onError(Throwable e) {
public void onNext(String s) {
Log.i(TAG, "onNext 现在的线程:" + Thread.currentThread().getName());
textView.setText(s);
observable.subscribe(subscriber);
create 现在的线程:RxCachedThreadScheduler-1
map 现在的线程:RxCachedThreadScheduler-1
onNext 现在的线程:main
onCompleted 现在的线程:main
并且Activity的textview显示为”hello world!这是尾巴~”;
当调用Observable.subscribe(),会返回一个Subscription对象。这个对象代表了被观察者和订阅者之间的联系。
可以使用unsubscribe来终止调用
修改以上代码
Subscription subscription = observable.subscribe(subscriber);
subscription.unsubscribe();
Log.i(TAG, "被终止:" + subscription.isUnsubscribed());
被终止:true
上面的代码为了方便理解没有使用链式调用,实际上,RxJava完全可以使用链式调用。
以上面的代码为例,使用链式调用后
Subscription subscription = Observable.create(new Observable.OnSubscribe&String&() {
public void call(Subscriber&? super String& subscriber) {
Log.i(TAG, "create 现在的线程:" + Thread.currentThread().getName());
subscriber.onNext("hello world!");
subscriber.onCompleted();
}).map(new Func1&String, String&() {
public String call(String s) {
Log.i(TAG, "map 现在的线程:" + Thread.currentThread().getName());
return s + "这是尾巴~";
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber&String&() {
public void onCompleted() {
Log.i(TAG, "onCompleted 现在的线程:" + Thread.currentThread().getName());
public void onError(Throwable e) {
public void onNext(String s) {
Log.i(TAG, "onNext 现在的线程:" + Thread.currentThread().getName());
textView.setText(s);
和上面的相同
如果只是输入数据(使用just),并且不关心Subscriber的OnError和onCompleted,可以更加精简
Subscription subscription = Observable.just("hello world!").map(new Func1&String, String&() {
public String call(String s) {
Log.i(TAG, "map 现在的线程:" + Thread.currentThread().getName());
return s + "这是尾巴~";
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1&String&() {
public void call(String s) {
Log.i(TAG, "onNext 现在的线程:" + Thread.currentThread().getName());
textView.setText(s);
使用lambda
Java8中可以使用lambda表达式,通过这个gradle插件,在Android中可以支持Lambda。
具体Android Studio上retrolambda的配置可参照
Observable.just("hello world!").map(s -& {
Log.i(TAG, "map 现在的线程:" + Thread.currentThread().getName());
return s + "这是尾巴~";
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(s -& {
Log.i(TAG, "onNext 现在的线程:" + Thread.currentThread().getName());
textView.setText(s);
使用Rxjava替代Handler实现单纯的线程切换
一般使用Rxjava都会有用create、just、from进行传参的操作,但有时候我不需要传参只是想切换一下线程而已。例如使用服务下载安装包之后,发送一个广播,这时候在其他页面接收广播时还是在子线程...
OkGo 结合Rxjava2 使用flatmap 做网络请求的链式调用。
最近工作中,需要在okgo的基础上做网络请求的链式调用,然后就查看了一些资料捣鼓了一下。OkGo github地址1.添加的依赖库compile 'com.lzy.net:okgo:3.0.4'
最简单易懂的RxJava2.0学习教程之RxJava2的基本使用(一)
去年RxJava2就发布了,在这之后一直做项目都在使用Rxjava2,觉得特别好用,目前网上的的资料很多,对于以前使用过RxJava1的朋友来说只需要看看更新文档就知道怎么使用了,但还有一些以前没用过...
Android 响应式编程 RxJava2 完全解析
RxAndroid全解析
RxJava 链式调用流程源码记录分析(以map()为例)
瞅了源码,记录下RxJava的链式调用原理。下文主要以 map()函数的调用流程分析
若不熟悉基本使用请看此文 给 Android 开发者的 RxJava 详解
) 实例public cl...
前段时间了解到MVP+Retrofit2+RxJava非常火,也确实好用。正好前几天咬牙研究了一番,故写一篇博客,和大家分享。此类资料很多,写的不好,高手勿喷。
RxJava2的介绍
用原话就是:RxJava2是一个在Java虚拟机上,使用可观察的序列构成基于事件的,异步的程序库。不理解没关系,可以类比成我们的AsyncTask,这样就好理解多了
简介面试的时候,我只是看了简单的看了下,Rxjava+Retrofit做请求的简单应用,当时也没发现有啥好的地方,面试官问了我个问题,你用Retrofit是如何解决链式请求问题的?,当时我懵逼了啥是链...
RxJava2+Retrofit+RxBinding解锁各种新姿势
本篇文章内容包含以下内容
RxJava2的基本介绍
RxJava2观察者模式的介绍
源码分析Rxjava2是如何完成链式调用的
源码分析Rxjava2是如何完成链式调用的
没有更多推荐了,编写多线程服务器实现多用户登录然后写多线程客户端实现链接登录服务器聊天【java吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:724,878贴子:
编写多线程服务器实现多用户登录收藏
编写多线程服务器实现多用户登录然后写多线程客户端实现链接登录服务器聊天
51CTO学院12年行业品牌,1600万用户选择,中国专业IT技能学习平台.java资深大牛授课,0基础从入门到精通,java报名与培训中心.
怎么写有大神会?
登录百度帐号RxJava在圈子里越来越火,相信很大的一个原因就是它的线程切换。它的线程切换可以用优雅来形容,链式调用,简单、方便。今天,就让我们来窥探一下RxJava的线程切换原理。本次拆轮子,还是按原样,通过小例子,研读RxJava源码等来理解整个过程、结构、原理,我们首要的是先对线程切换的原理有个全局的概览,细节再慢慢来深入。
线程的切换都是通过subscribeOn或者observeOn来进行,生产者的执行线程只受subscribeOn控制,不受observeOn影响。subscribeOn指定的线程环境能一直维持到第一次observeOn出现之前。要讲线程切换原理之前,我们先来看一下下面的几个类定义:
Operator/**
* Operator function for lifting into an Observable.
public interface Operator&R, T& extends Func1&Subscriber&? super R&, Subscriber&? super T&& {
// cover for generics insanity
Operator是Observable中定义的接口,即用户的逻辑操作,RxJava框架会调用lift方法将Operator包装成为Observable。
ObserveOnSubseriberObserveOnSubseriber是被订阅者的类,处理用户数据逻辑,也即生产者,用来产生用户数据的。
OperatorObserveOnOperatorObserveOn是订阅者的类,接收数据的,也即消费者,消费生产者发送过来的数据。
WorkerWorker是线程真正执行的地方,也就是单独新建的一个线程或线程池中的某个线程。
2 原理解析
我们先创建一个Observable:
Observable.just(null)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
just方法又是调用的ScalarSynchronousObservable,然后new一个OnSubscribe作为构造函数的参数,暂且叫做1号OnSubscribe,这个下面会再提到,也是线程切换的区别所在:
protected ScalarSynchronousObservable(final T t) {
super(new OnSubscribe&T&() {
public void call(Subscriber&? super T& s) {
s.onNext(t);
s.onCompleted();
this.t = t;
线程切换的要点在lift()函数里面,都是基于同一个基础的变换方法: lift(Operator)
先来看一下它的源码:
public final &R& Observable&R& lift(final Operator&? extends R, ? super T& operator) {
return new Observable&R&(new OnSubscribe&R&() {
public void call(Subscriber&? super R& o) {
Subscriber&? super T& st = hook.onLift(operator).call(o);
// new Subscriber created and being subscribed with so 'onStart' it
st.onStart();
onSubscribe.call(st);
} catch (Throwable e) {
// localized capture of errors rather than it skipping all operators
// and ending up in the try/catch of the subscribe method which then
// prevents onErrorResumeNext and other similar approaches to error handling
if (e instanceof OnErrorNotImplementedException) {
throw (OnErrorNotImplementedException) e;
st.onError(e);
} catch (Throwable e) {
if (e instanceof OnErrorNotImplementedException) {
throw (OnErrorNotImplementedException) e;
// if the lift function failed all we can do is pass the error to the final Subscriber
// as we don't have the operator available to us
o.onError(e);
我们可以看到,调用lift()方法后(即执行subscribeOn或observeOn),是返回一个新的Observable,而不是调用者的Observable,这里同样是重新创建了一个OnSubscribe,暂且叫做2号OnSubscribe,我们再回头看看,这个OnSubscribe与前面提到的just()方法里面调用到的OnSubscribe不是同一个对象。
这里是线程切换的关键点。当调用链来到lift()方法后,使用的是lift()所返回的新的 Observable,也就是它所触发的onSubscribe.call(subscriber)也是用新的Observable中的新 OnSubscribe,即我们上面命名的2号OnSubscribe。
3 OperatorSubscribeOn
再来看lift()函数的源码,它的第二个try方法体里面有个onSubscribe,这个OnSubscribe就是我们前面定义的1号onSubscribe,它就是我们调用just()方法后创建的原始Observable。
那它是怎么做到切换线程的呢?如上面的例子,subscribeOn(()),它通过下面的代码(举例)产生一个新的Subscriber:
Subscriber&? super T& st = hook.onLift(operator).call(o);//将新的Subscriber对象o传递给OperatorSubscribeOn,它里面的call()方法去创建新的Worker线程
//OperatorSubscribeOn的call(o)方法@Override
public Subscriber&? super Observable&T&& call(final Subscriber&? super T& subscriber) {
final Worker inner = scheduler.createWorker();//新建线程
subscriber.add(inner);
return new Subscriber&Observable&T&&(subscriber) {
public void onCompleted() {
// ignore because this is a nested Observable and we expect only 1 Observable&T& emitted to onNext
public void onError(Throwable e) {
subscriber.onError(e);
public void onNext(final Observable&T& o) {
inner.schedule(new Action0() {
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber&T&(subscriber) {
public void onCompleted() {
subscriber.onCompleted();
public void onError(Throwable e) {
subscriber.onError(e);
public void onNext(T t) {
subscriber.onNext(t);
public void setProducer(final Producer producer) {
subscriber.setProducer(new Producer() {
public void request(final long n) {
if (Thread.currentThread() == t) {//如果是当前线程,则在当前线程执行
// don't schedule if we're already on the thread (primarily for first setProducer call)
// see unit test 'testSetProducerSynchronousRequest' for more context on this
producer.request(n);
} else {//不是当前线程,将在新创建的Worker线程inner中执行
inner.schedule(new Action0() {
public void call() {
producer.request(n);
然后,通过调用1号OnSubscribe的call()方法 onSubscribe.call(st) 将新创建的Subscriber与原始的Observable关联起来,即新的Subscriber去订阅原始的Observable。这样,生产者
通过上面的代码可以知道,Scheduler类其实并不负责异步线程处理,它只负责通过createWorker()类创建出一个Worker对象,真正负责任务的延时处理。
4 OperatorObserveOn
observeOn方法内部也是调用了lift()方法,然后创建一个operator,
//OperatorObserveOn.java@Override
public Subscriber&? super T& call(Subscriber&? super T& child) {
if (scheduler instanceof ImmediateScheduler) {
// avoid overhead, execute directly
return child;
} else if (scheduler instanceof TrampolineScheduler) {
// avoid overhead, execute directly
return child;
ObserveOnSubscriber&T& parent = new ObserveOnSubscriber&T&(scheduler, child);
parent.init();
return parent;
public ObserveOnSubscriber(Scheduler scheduler, Subscriber&? super T& child) {
this.child = child;
this.recursiveScheduler = scheduler.createWorker();//创建新的worker线程
if (UnsafeAccess.isUnsafeAvailable()) {
queue = new SpscArrayQueue&Object&(RxRingBuffer.SIZE);
queue = new SynchronizedQueue&Object&(RxRingBuffer.SIZE);
this.scheduledUnsubscribe = new ScheduledUnsubscribe(recursiveScheduler);
protected void schedule() {
if (COUNTER_UPDATER.getAndIncrement(this) == 0) {
recursiveScheduler.schedule(action);//用相应的线程进行数据输出调度
结合扔物线大大的图如下:
未完待续......
从源码分析RxJava在Android里线程切换的实现
作为近两年好评如潮的Rx系列,最近研究了下Android用到的RxJava的线程切换流程。本文是对常用的的io线程加载数据并在主线程更新界面的流程分析。...
RxJava切换线程是怎么实现的呢?
RxJava切换线程是怎么实现的呢?
lift变换过程
要明白 RxJava 切换线程切换线程的原理,我们首先得理解变换过程。
对于变换过程,我的理解就是:
Observable.cr...
RxJava(RxAndroid)线程切换机制
自从项目中使用RxJava以来,可以很方便的切换线程。至于是怎么实现的,一直没有深入的研究过!本篇文章就是分析RxJava的线程模型。
  RxJava基本使用
  先上一个平时使用RxJava切...
一张图搞定-RxJava2的线程切换原理和内存泄露问题
RxJava2的线程切换原理和内存泄露问题分析
不管你信不信,一张图搞定此问题
Rxjava原理探索:切换线程,变换
在之前的几篇博客中,我编写了一篇有关Rxjava学习笔记的,还有一个是RxJava使用示例(一): 实现Rxbus代替eventbus(这篇博文其实还不算完善,因为没有对被观察者发出的时间进行一个筛选...
RxJava(11-线程调度Scheduler)
转载请标明出处:
http://blog.csdn.net/xmxkf/article/details/
本文出自:【openXu的博客】目录:使用示例
subscribeOn...
迷之RxJava —— 线程切换
RxJava最迷人的是什么?
答案就是把异步序列写到一个工作流里!和javascript的Promise/A如出一辙。
OK,在java中做异步的事情在我们传统理解过来可不方便,而且,如果要让异步...
一起来造一个RxJava,揭秘RxJava的实现原理
RxJava是一个神奇的框架,用法很简单,但内部实现有点复杂,代码逻辑有点绕。我读源码时,确实有点似懂非懂的感觉。网上关于RxJava源码分析的文章,源码贴了一大堆,代码逻辑绕来绕去的,让人看得云里雾...
RxJava(十五)RxJava线程的自由切换
RxJava系列文章目录导读:
一、RxJava create操作符的用法和源码分析
二、RxJava map操作符用法详解
三、RxJava flatMap操作符用法详解
[Android开发] RxJava2之路三 - 调度器Scheduler与线程控制
一、简介RxJava是一个异步的框架,使用Scheduler调度器进行很多操作,例如可以对线程进行控制。二、调度器种类常用的是 Schedulers.io()进行耗时操作、和AndroidSchedu...
没有更多推荐了,博客分类:
在前面,我们已经讲了,我们也知道了他的代码实现,在了解之后,我们很容易就能够发现他有一个最大的缺点,就是插入和删除需要移动大量的元素,这显然是很耗费时间的,于是,为了解决这个问题,就出现了链式存储结构。
我学习的时候是看程杰的《大话数据结构》的,同时结合我们的经典教材清华出版社的《数据结构》,但是在学习过程中,我不小心把“插入到第i个位置之后”理解成了“插入到第i个位置”,所以我后面的程序跟书上的范例有些不一样,但是万变不离其宗,它运用的始终是我们的数据结构——线性表的链式存储结构。
由于理解错了课本的一些意思,所以代码显得更复杂了一点点,好吧,言归正传,继续讲我们代码是如何实现的。
第一步,定义一个接口,其实这个接口跟前面顺序存储结构的接口定义是一样的,后面我只是改了下名字和重新更换了包名而已,但这不影响我们的代码:
package com.stucture.
* 线性表顺序存储结构的接口
* 指的是用一段地址连续的存储单元一次存储线性表的数据元素
* @ClassName: ISqList
* @author 小学徒
public interface IList&T& {
* 获得元素
* @param loc 需要获得的第loc个元素
public T getElem(int loc);
* 插入元素
* @param loc 元素的插入位置
* @param t 需要插入的元素
是否成功插入
public boolean insertElem(int loc, T t);
* 删除元素
* @param i 需要删除元素的位置
public T deleteElem(int i);
第二步,定义我们的节点类:
package com.stucture.list.linkL
* 链表中的结点
* @ClassName: Node
* @author 小学徒
public class Node&T& {
//需要存储的数据信息
private Node&T& //后继结点
public T getData() {
public void setData(T data) {
this.data =
public Node&T& getNext() {
public void setNext(Node&T& next) {
this.next =
第三步,定义我们的链表及其基本操作,代码如下:
package com.stucture.list.linkL
import com.stucture.list.IL
* @ClassName: LinkList
* @author 小学徒
public class LinkList&T& implements IList&T&{
private Node&T& //链表的结点
//链表的长度
public LinkList(Node&T& head) {
this.head =
//获取元素
public T getElem(int loc) {
int j = 1; //计数器
Node&T& n = //指向第一个结点
while(n != null) { //n不为空时,循环继续寻找第loc个结点
if(j == loc) { //找到第一个元素时返回
return n.getData();
n = n.getNext();
//插入元素
public boolean insertElem(int loc, T t) {
if(length + 1 & loc) {
System.out.println("非法插入");
if(head == null && loc == 1) { //当第一次插入的时候
head = new Node&T&(); //第一次使用,必须创建对象
head.setData(t);
} else if(head != null && loc == 1) { //但不是第一次插入,但是插入的位置是第一个时
Node&T& tempNode = new Node&T&(); //生成一个新的结点
tempNode.setData(t);
tempNode.setNext(head);
head = tempN //把头换成新插入的结点
} else { //当不是第一次插入并且插入的不是第一个时
Node&T& n = this.
int j = 1; //计数器
while(n != null && j & loc - 1) {
n = n.getNext();
Node&T& tempNode = new Node&T&(); //生成一个新的结点
tempNode.setData(t);
tempNode.setNext(n.getNext()); //将n的后继结点赋值给新的结点的后继
n.setNext(tempNode);
//删除元素
public T deleteElem(int loc) {
if(head == null || loc & length) {
System.out.println("非法删除");
if(head != null && loc == 1) {
old = head.getData();
head = head.getNext();
Node&T& n = this.
int j = 1; //计数器
while(n != null && j & loc - 1) {
n = n.getNext();
old = n.getNext().getData();
n.setNext(n.getNext().getNext());
public Node&T& getHead() {
public void setHead(Node&T& head) {
this.head =
public int getLength() {
public void setLength(int length) {
this.length =
第四步,我们下面就写一个比较完善的代码测试,在下面的代码中,我是通过随机数来生成一些必要的数据来测试的,只要多运行几遍,还是能够测试比较完善的,不过封装的可能有点不太好,如果读者看了以后有什么更好的建议,还希望能够指出,当然因为该链式存储结构和顺序存储结构都是同一个接口的实现,所以测试方法是可以一样的,只是把实现类转换了而已。但是由于时间问题,我就没有去修改了,有兴趣的读者可以自行修改,有问题的可以在此留言共同讨论共同进步,我有空的时候也会更改并上传到博客的,下面继续代码:
package com.stucture.list.linkL
import java.util.R
public class LinkListTest {
final int MAX = 25;
Random r = new Random();
LinkList&Integer& linkL
public LinkListTest() {
initSeqList();
//创建一个线性表顺序存储结构
public void initSeqList() {
linkList = new LinkList&Integer&(null);
int length = Math.abs(r.nextInt(MAX)); //使用Random随机产生一个25左右的值,使用Math.abs()函数来取绝对值
System.out.println("产生的链表长度为 :" + length);
for (int i = 1; i &= i++) { //为生成的链表赋值,同时也测试了插入值的方法
int j =r.nextInt(MAX);
System.out.print(j + " ");
if(!linkList.insertElem(i, j)) {
System.exit(0);
System.out.println("\n原始链表是 :");
display(linkList);
//测试删除方法
public void deleteElem() {
int i = r.nextInt(MAX);
System.out.println("\n\n删除的位置是:" + i);
Integer deleteNumber = linkList.deleteElem(i);
if( deleteNumber == null) {
System.exit(0);
System.out.println("删除的元素是 : " + deleteNumber);
System.out.println("删除元素后链表是 :");
display(linkList);
//测试随机插入方法
public void insertByRandom() {
int i = r.nextInt(MAX);
System.out.println("\n\n随机插入位置是 :" + i);
int elem = r.nextInt(MAX);
System.out.println("随机插入数据是 :" + elem);
linkList.insertElem(i, elem);
System.out.println("随机插入数据后链表是 :");
display(linkList);
//数据展示
void display(LinkList&Integer& linkList) {
Node&Integer& node = linkList.getHead();
while(node != null) {
System.out.print(node.getData() + " ");
node = node.getNext();
System.out.println("链表的长度为 :" + linkList.getLength());
//获取元素
public void getElem() {
int i = r.nextInt(MAX);
System.out.println("\n获取位置为 :" + i);
System.out.println("获取到的元素为 : " + linkList.getElem(i));
public static void main(String[] args) {
LinkListTest s = new LinkListTest();
s.insertByRandom();
s.deleteElem();
s.getElem();
运行结果同样我不一一把各种结果列出啦,读者可以自己运行多几遍来进行学习:
产生的链表长度为 :23
5 19 18 12 6 12 15 19 16 21 13 16 5 4 18 9 9 18 17 13 16 6 17
原始链表是 :
5 19 18 12 6 12 15 19 16 21 13 16 5 4 18 9 9 18 17 13 16 6 17 链表的长度为 :23
随机插入位置是 :24
随机插入数据是 :0
随机插入数据后链表是 :
5 19 18 12 6 12 15 19 16 21 13 16 5 4 18 9 9 18 17 13 16 6 17 0 链表的长度为 :24
删除的位置是:11
删除的元素是 : 13
删除元素后链表是 :
5 19 18 12 6 12 15 19 16 21 16 5 4 18 9 9 18 17 13 16 6 17 0 链表的长度为 :23
获取位置为 :12
5 19 18 12 6 12 15 19 16 21 16 5 获取到的元素为 : 5
浏览: 88703 次
来自: 广州
在删除的时候最后一个元素并没有移除掉
lenient315 写道那个。。。我想说,java语言对对象 ...
那个。。。我想说,java语言对对象采用的不是引用调用,实际上 ...
feipigzi 写道feipigzi 写道我记得第一天看ja ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 java虚拟机安卓版apk 的文章

 

随机推荐