Java基础笔试题

目录:

1、JSP页面之间传递参数,主要有哪几种方法?

其中哪种方法可以实现在多个jsp页面之间传递参数。
例如把第一个页面的参数传递到第三个页面?请写出相应的示例代码。

(1)直接在URL请求后添加 (2)jsp:param(3)设置session和request

1)直接在URL请求后添加
如:< a href="thexuan.jsp?action=transparams&detail=directe">直接传递参数</a>
特别是在使用response.sendRedirect做页面转向的时候,也可以用如下代码:
response.sendRedirect("thexuan.jsp?action=transparams&detail=directe") ,可用request.getParameter(name)取得参数
2)jsp:param
它可以实现主页面向包含页面传递参数,如下:
< jsp:include page="Relative URL">< jsp:param name="paramname" value="paramvalue"/>
</jsp:include>
还可以实现在使用jsp:forward动作做页面跳转时传递参数,如下:
< jsp:forward page="Relative URL">< jsp:param name="paramname" value="paramvalue"/></jsp:forward>
通过这种方式和一般的表单参数一样的,也可以通过request.getParameter(name)取得参数
3)设置session和request
通过显示的把参数放置到session和request中,以达到传递参数的目的
session.setAttribute(name,value); 
request.setAttribute(name,value);
取参数:
value=(value className)session.getAttribute(name); 
value=(value className)request.getAttribute(name);

怎么在多个JSP页面之间进行参数传递?需要使用JSP的内置作用域对象session。利用它的两个方法setAttribute(),getAttribute() 下面的这个实例实现了把第一个JSP页面的参数传递给第三个页面的功能

代码如下:1.jsp

< html>< form method=get action=2.jsp> 
		whats your name?
		< input type=text name=username>< input type=submit value=submit></form></html>

2.jsp

< html>          
	< form method=post action="3.jsp?pass=11">          
	<% 
		String name=request.getParameter("username");           
		session.setAttribute("username",name);           
	%>          
	Your name is:<%=request.getParameter("username")%>          
	< br>whats your hobby< input type=text name=hobby>          
	< input type=submit value=submit>          
	</form>  
</html>

3.jsp

< html>      
	your name is:<%=session.getAttribute("username")%>          
	< br>          
	your hobby is:<%=request.getParameter("hobby")%>          
	< br>          
	your password is:<%=request.getParameter("pass")%>          
	< br>          
</html>

2、请描述java设计模式中,“单例模式”(Singleton)的原理,实现单例模式的方式以及代码。

单例模式(Singleton Pattern)是 Java中最简单的设计模式之一。
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

懒汉式(立即加载)
线程安全。

public class Singleton {
	private Singleton(){};
	private static Singleton instance = new Singleton();
	public static Singleton getInstance(){
		return instance;
	}
}

饿汉式(延迟加载)

public class Singleton2 {

 /**
 * 私有构造
 */
 private Singleton2() {
 	System.out.println("构造函数 Singleton2");
 }

 /**
 * 初始值为 null
 */
 private static Singleton2 single = null;

 /**
 * 静态工厂方法
 * @return 单例对象
 */
 public static Singleton2 getInstance() {
 	if(single == null){
 		System.out.println("getInstance");
 		single = new Singleton2();
 	}
 	return single;
 }

 public static void main(String[] args){
 	System.out.println("初始化");
 		Singleton2 instance = Singleton2.getInstance();
 	}
 }

同步锁(解决线程安全问题)

public class Singleton3 {

 /**
 * 私有构造
 */
 private Singleton3() {}

 /**
 * 初始值为 null
 */
 private static Singleton3 single = null;

 public static Singleton3 getInstance() {

 // 等同于 synchronized public static Singleton3 getInstance()
 	synchronized(Singleton3.class){
 		// 注意:里面的判断是一定要加的,否则出现线程安全问题
 			if(single == null){
 				single = new Singleton3();
 			}
 		}
 		return single;
 	}
 }

双重检查锁(提高同步锁效率)

public class Singleton4 {

private Singleton4() {}

/**
* 初始值为 null
*/
private static Singleton4 single = null;

/**
* 双重检查锁
* @return 单例对象
*/
	public static Singleton4 getInstance() {
		if (single == null) {
			synchronized (Singleton4.class) {
				if (single == null) {
					single = new Singleton4();
				}
			}
		}
		return single;
	}
}

静态内部类
既能延迟加载,又能线程安全。

public class Singleton5 {
	private Singleton5() {}

/**
* 静态内部类
*/
	private static class InnerObject{
		private static Singleton5 single = new Singleton5();
	}

	public static Singleton5 getInstance() {
		return InnerObject.single;
	}
}

内部枚举类实现(防止反射攻击)

public class SingletonFactory {
/*
**
* 内部枚举类
*/
	private enum EnumSingleton{
		Singleton;
		private Singleton6 singleton;

//枚举类的构造方法在类加载是被实例化
		private EnumSingleton(){
			singleton = new Singleton6();
		}
		public Singleton6 getInstance(){
			return singleton;
		}
	}

	public static Singleton6 getInstance() {
		return EnumSingleton.Singleton.getInstance();
	}
}

class Singleton6 {
	public Singleton6(){}
}

3、JSP有哪些内置对象?它们的作用分别是什么?

(1)Request
Request对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。Request对象的作用域为一次请求。

(2)Session
Session对象由服务器自动创建的与用户请求相关的对象。服务器为每一个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态。Session对象内部使用Map类来保存数据。

(3)Response
Response代表对客户端的响应,主要是将JSP容器处理过的对对象传回客户端。Response对象也有作用域,它只在JSP页面有效。

(4)Application
Application对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。与session对象相比,application的声明周期更长,类似于系统的“全局变量”。

(5)Out
Out对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区。在使用out对象输出数据时,可以对数据缓存区进行操作,及时清除缓冲区中的残余数据,为其他的输出让出缓冲空间。待数据输出完毕后,要及时关闭输出流。

(6)Pagecontext
Pagecontext对象的作用是取得任何范围的参数,通过它可以获取JSP页面的out、request、response、session、application等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用pageContext对象。

(7)Config
Config对象的主要作用是取得服务器的配置信息。通过pageContext对象的getServletConfig()方法可以获取一个config对象。当一个Servlet初始化时,容器把某些信息通过config对象传递给这个Servlet。开发者可以在web.xml文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。

(8)Page
Page对象代表JSP本身,只有在JSP页面内才是合法的。Page隐含对象本质上包含当前Servlet接口引用的变量,类似于Java编程中的this指针。

(9)Exception
Exception对象的作用是显示异常信息,只有在包含isErrorPage=“true”的页面中才可以被使用。

4、作用域public,private,protected,以及不写时的区别?

(1)public可以本类、同一个包、子类、其他包下访问。
(2)Private只能本类访问。
(3)Protected可以本类、同一个包、子类下访问。
(4)不写 默认可以在本类和同一个包下访问。

5、char型变量中能不能存贮一个中文汉字?为什么?

可以,java采用unicode编码,两个字节表示一个字符,char在java中是两个字节(16位),所以,可以存储一个中文汉字。

6、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()?它们有何区别?

equals(),==判断的是两个对象是否是同一对象,equals方法是判断两个对象的引用是否一致。

7、面向对象的特征有哪些方面 ?

抽象、继承、封装、多态

(1)抽象
忽略一个主题中与当前目标无关的东西,专注的注意与当前目标有关的方面。(就是把现实世界中的某一类东西,提取出来,用程序代码表示,抽象出来的一般叫做类或者接口)。
(2)继承
一种联结类的层次模型,并且允许和鼓励类的重用,提供一种明确表达共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。
(3)封装
封装是面向对象的特征之一,是对象和类概念的主要特性。封装就是把过程和数据包围起来,对数据的访问只能通过已定义的界面。如私有变量,用set,get方法获取。
(4)多态
多态是指允许不同类的对象对同一消息做出响应。多态性包括参数化多态性和包含多态性。

8、给我一个你最常见到的runtime exception?

空指针异常 NullPionterException

类转换异常 ClassCastException

索引超出异常 IndexOutOfBoundsException

数组下标越界异常 ArrayIndexOutOfBoundsException

字符串截取下标越界 StringIndexOutOfBoundsException

数字格式化异常 NumberFormatException

算术异常 ArithmeticException

非法数据异常 IllegalArgumentException

非法语句异常 IllegalStateException

9、List, Set, Map是否继承自Collection接口?

List和Set继承自Collection,Map不是。

Collection 和 Map 的区别
容器内每个为之所存储的元素个数不同。
Collection类型者,每个位置只有一个元素。
Map类型者,持有 key-value pair,像个小型数据库。

List,Set,Map将持有对象一律视为Object型别。
Collection、List、Set、Map都是接口,不能实例化。
继承自它们的 ArrayList, Vector, HashTable, HashMap是具象class,这些才可被实例化。

10、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

(1)Abstract是抽象的,指的是方法只有声明而没有实现,他的实现要放入声明该类的子类中实现。
(2)Static是静态的,是一种属于类而不属于对象的方法或者属性。
(3)Synchronized是同步,是一种相对线程的锁。
(4)Native本地方法,这种方法与抽象方法及其类似,它也只有方法声明,没有方法实现,但是它与抽象方法不同的是,它把具体实现转交给了本地系统的函数库,而没有通过虚拟机,可以说是java与其他语言通讯的一种机制。
(5)为什么这些关键字不能和abstract混用
首先abstract与static,声明static说明可以直接用类名调用该方法,声明abstract说明需要重写子类重写该方法,如果同时声明static和abstract,用类名调用一个抽象方法肯定不行。

Synchronzied是同步线程锁,然而同步是需要有具体操作才能同步的,如果像abstract只有方法声明,那同步一些什么东西就会成为一个问题,当然抽象方法在被子类集成以后,可以添加同步。

Native本身就和abstract冲突,他们都是方法的声明,只是一个把方法实现移交给子类,另一个移交给本地系统,如果同时实现,就会发生冲突。

注:final、private、static都不能和abstract同时使用

11、接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承实体类(concrete class)?

可以,
(1)接口是可以被接口继承的,即通过关键字extends声明一个接口是另一个接口的子接口。由于接口中的方法和常量都是public,子接口将继承父接口中的全部方法和常量。
(2)抽象类可以实现接口,当一个类声明实现一个接口而没有实现接口中的所有方法,那么这个类就是抽象类(abstract类)。
(3)抽象类可以继承实体类。

12、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递。Java编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用的一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的。

13、介绍JAVA中的Collection FrameWork(包括如何写自己的数据结构)?

|-Connection
|–List:元素可以重复,有序(存入顺序和取出顺序一致)
|----ArrayList:底层数据结构是数组,查询快,增删慢;线程不安全,效率高
|----Vector:底层数据结构是数组,查询库,增删慢;线程安全,效率低
|----LinkedList:底层数据结构是链表,查询慢,增删快;线程不安全,效率高
|–Set:元素无序,不可以重复
|----HashSet:底层数据结构是哈希表。如果想按照自己的需求实现去掉重复值。
必须重写hashCode和equals方法。
|----LinkedHashSet:底层数据结构是链表和哈希表
|----TreeSet:底层数据结构是二叉树。

14、抽象类与接口有什么区别?

(1)抽象类是由abstract修饰的,接口是interface修饰的
(2)抽象类要被子类继承,接口要被类实现
(3)接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
(4)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
(5)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
(6)一个类只能继承一个抽象类,而一个类却可以实现多个接口
(7)抽象类可以有构造器,接口不能有构造器

15、int和Integer有什么区别?

(1)Int是java的基本数据类型,Integer是对Int的包装类
(2)Integer变量必须实例化后才能使用,而int变量不需要
(3)Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
(4)Integer的默认值是null,int的默认值是0

16、Java中的异常处理机制的简单原理和应用?

Java对异常进行了分类,不同类型的异常使用了不同的java类,所有异常的根类为java.lang.Throwable,Throwable派生了2个子类:Error和Exception。

Error表示程序本身无法克服和恢复的一种严重错误,程序只有死的份,如内存溢出和死锁等系统问题。

Exception表示还能克服和恢复,其中又分为系统异常和普通异常。
系统异常是软件本身缺陷导致的问题,也就是软件开发问题考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但这种情况下可以选择让软件运行死掉。如数组越界问题(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException),类转换异常(ClassCastException);
普通异常是运行环境的变化或异常导致的问题,是用户能够克服的问题,如网络掉线、硬盘空间不足、IO异常等。

Java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try…catch处理或throws声明继续抛给上层调用方法处理

17、垃圾回收的优点和原理。并考虑2种回收机制多线程有几种实现方法,都是什么?

(1)java语言最显著的特点就是引入了垃圾回收机制,它使java程序员在编写程序时不再考虑内存管理的问题。
(2)由于有了这个垃圾回收机制,java中的对象不再有“作用域”的概念,只有引用的对象才有“作用域
(3)垃圾回收机制有效的防止了内存泄漏,可以有效的使用可使用的内存
(4)垃圾回收器通常作为一个单独的低级别的线程运行,在不可预知的情况下对内存堆中已死亡的或很长时间没有用过的对象进行清除和回收
(5)程序员不能实时的对某个对象或所有对象调用垃圾回收器进行垃圾回收
(6)垃圾回收有分代复制垃圾回收标记垃圾回收增量垃圾回收

18、线程的基本概念、线程的基本状态以及状态之间的关系。

(1)继承Thread类,重写run()方法
(2)实现Runnable接口,重写run()方法
(3)通过Callable和FutureTask创建线程
(4)通过线程池创建线程
同步有两种实现方式,分别为synchronized,wait与notify
(1)wait():使一个线程处于等待状态,并且释放所持有的对象的lock
(2)sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法
// 调用此方法要捕捉InterruptedException异常
(3)notify():唤醒一个处于等待状态的线程,注意的是在调用此方法时,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而不是按优先级。
notifyAll():唤醒所有处于等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让他们竞争。

19、sleep() 和 wait() 有什么区别?

sleep()和wait()都是线程暂停执行的方法。
(1)这两个方法来自不同的类,分别是Thread和Object,sleep方法属于Thread类中的静态方法,wait属于Object的成员方法。
(2)Sleep()是线程类(Thread)的方法,不涉及线程通信,调整时会暂停此线程的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait() 是Object的方法,用于线程间的通信,调用时会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才进入对象锁定池准备获得对象锁进入运行状态。
(3)wait(),notify和notifyAll只能在同步控制方法或者同步控制块里边使用,而sleep可以在任何地方使用。
(4)Sleep()方法必须捕获异常InterruptedException,而wait()/notify()以及notifuAll()不需要捕获异常。

20、简述synchronized和java.util.concurrent.locks.Lock的异同?

主要相同点:Lock能完成synchronized所实现的所有功能。
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。
Synchronized会自动释放锁,而Lock一定要求程序员手工释放,而且必须在finally从句中释放。

21、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

(1)其他方法前是否加了synchronized关键字,如果没加,则能。
(2)如果这个方法内部调用了wait,则可以进入其他synchronized方法。
(3)如果其他方法都加了synchronized关键字,并且内部没有调用wait,则不能。
(4)如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。

22、同步和异步有何异同,在什么情况下分别使用他们?举例说明。

同步交互:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有个等待过程;
异步交互:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。

23、描述一下JVM加载class文件的原理机制?

Java中的所有类,都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中。在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的,除非我们有特殊的用法,像是反射,就需要显示的记载所需要的类。

类装载方式,有两种:
(1)隐式装载,程序在运行过程中当碰到通过new等方式生成对象时,隐式调用类加载器加载对应的类到JVM中。
(2)显示装载,通过class.froname()等方法,显示加载需要的类。
Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销。

24、什么是java序列化,如何实现java序列化?

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化(将对象转换成二进制)。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间,序列化是为了解决在对 对象流进行读写操作时所引发的问题。把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。

序列化的实现
将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象时可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流),接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

25、是否可以从一个static方法内部发出对非static方法的调用?

不可以。因为非static方法是要与对象关联在一起的,必须在创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何的实例对象,如果从一个static的方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部不可以发出对非static方法的调用。

26、写clone()方法时,通常都有一行代码,是什么?

super.clone()
Clone()方法的作用:克隆,将现有的对象复制一份,产生一份与原来对象一样的对象,但注意克隆出来的对象存放的内存地址和被克隆的对象不一样。
Object对象有一个clone()方法,

protected Object clone() throws CloneNotSupportedException {  
    if (!(this instanceof Cloneable)) {  
        throw new CloneNotSupportedException("Class doesn't implement Cloneable");  
    }  

    return internalClone((Cloneable) this);  
}  

Clone方法会判断当前对象是否是一个Cloneable的实现类,那么我们使用clone()方法,就得实现这个接口:

public class MyClone {
    public static void main(String[] args) {
        Person p = null;
        Person p2 = null;
        try {
            p = new Person();
            p2 = (Person) p.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(p);
        System.out.println(p2);
    }

}
//实现Cloneable接口,重写clone()方法
class Person implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

重写clone()方法的时候,需要先克隆父类,所以一般来说,通常都有一行代码是super.clone()
还有我们在使用clone的时候,会有浅克隆和深克隆之分,一定要注意,浅克隆克隆出的对象,该对象里的引用类型的变量存储的还是原对象的值,有时候修改可能会修改到原对象引用的对象。

27、forward 和redirect的区别。

(1)请求方不同
redirect:客户端发起的请求;
forward:服务端发起的请求;

(2)浏览器地址表现不同
redirect:浏览器地址显示被请求的;
forward:浏览器地址不显示被请求的url;

(3)参数传递不同
redirect:重新开始一个request,原页面的request生命周期结束。
forward:forward另一个连接的时候。Request变量是在其声明周期内的。另一个页面也可以使用,其实质是把目标地址include

(4)底层运作不同
redirect:发送的请求信息又回送给客户机,让客户机再转发到另一个资源上,需要在服务器和客户机之间增加一次通信。
forward:服务器端直接找到目标,并include过来

(5)定义不同
直接转发方式(Forward):客户端和浏览器只发出一次请求,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每个信息资源是共享的。

28、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?

(1)jsp经编译后就变成了servlet(jsp本质就是servlet,jvm只能识别java类,不能识别jsp代码,web容器将jsp的代码编译成jvm能够识别的java类)
(2)Jsp更更擅长表现于页面显示,servlet更擅长于逻辑控制
(3)setvlet中没有内置对象,jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象及HttpServlet对象得到
(4)jsp是servlet的一种简化,使用jsp只需要完成程序员需用输出到客户端的内容,jsp中的java脚本如何镶嵌到一个类中,由jsp容器完成,而servlet则是个完整的java类,这个类的service方法用于生成对客户端的响应

29、在MVC中如何保持sessions

可以通过三种方式保持:tempdata、viewdata、viewbag

tempdata,viewdata和viewbag之间的不同点
Temp data :在不同的控制器或动作间转换时保持数据。另外,进行页面转向时,tempdata可以保持数据。它是一个内部的Session变量。
View data:可以在控制器和视图间保持数据。
View Bag:它是视图数据的动态包装。使用Viewbag不需要类型转换。它使用的是内部动态关键词。

冒泡排序

package com.demo;

import java.util.Arrays;

public class Test {
	/**
	 * 冒泡排序
	 * @param data
	 */
	public static void bubblesort(int[] data){
		for(int i=1;i<data.length;i++){	//第 i 次排序
			for(int j=0;j<data.length-i;j++){	//从索引为 j 的数开始
				if(data[j] > data[j+1]){	//相邻元素两两对比
					int temp = data[j+1];	// 元素交换
					data[j+1] = data[j];
					data[j] = temp;
				}
			}
		}
		System.out.println("冒泡排序:"+Arrays.toString(data));
	}
	public static void main(String[] args) {
		int[] data = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
		//冒泡排序
		bubblesort(data);
	}
}

快速排序

package com.demo;

import java.util.Arrays;

public class Test {
	/**
	 * 快速排序
	 * @param data 数据
	 * @param low 基准位下标
	 * @param high 数组最大下标
	 */
	public static void quicksort(int[] data, int low, int high){
		int i,j,temp,t;
		if(low > high){
			return;
		}
		i=low;
		j=high;
		//temp就是基准位
		temp = data[low];
		System.out.println("基准位:"+temp);
		
		while(i < j){
			//先看右边,依次往左递减
			while(temp <= data[j] && i < j){
				j--;
			}
			//再看左边,依次往右递增
			while(temp >= data[i] && i < j){
				i++;
			}
			//如果满足条件则交换
			if(i < j){
				System.out.println("交换:"+ data[i] + "和" +data[j]);
				t = data[j];
				data[j] = data[i];
				data[i] = t;
				System.out.println(Arrays.toString(data));
			}
		}
		//最后将基准位与i和j相等的数字交换
		System.out.println("基准位"+temp+"和i、j相遇的位置"+data[i]+"交换");
		data[low] = data[i];
		data[i] = temp;
		System.out.println("快速排序:"+Arrays.toString(data));
		System.out.println("----------------------------------");
		
		//递归调用左半数组
		quicksort(data, low, j-1);
		//递归调用右半数组
		quicksort(data, j+1, high);
		
	}
	
	public static void main(String[] args) {
		int[] data = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
		//快速排序
		quicksort(data, 0, data.length-1);
	}
}

归并排序

package com.demo;

import java.util.Arrays;

public class Test {
	/**
	 * 归并排序
	 * @param data
	 */
	public static void mergesort(int[] data){
		sort(data, 0, data.length-1);
		System.out.println(Arrays.toString(data));
	}
	public static void sort(int[] arr,int l,int r){
		if(l == r){
			return;
		}
		int mid = l + ((r-l) >> 1);
		sort(arr,l,mid);
		sort(arr,mid+1,r);
		merge(arr, l, mid, r);
	}
	public static void merge(int[] arr,int l ,int mid,int r){
		int[] temp = new int[r-l+1];
		int i = 0;
		int p1 = l;
		int p2 = mid +1;
		//比较左右两部分的元素,哪个小,把那个元素填入temp中
		while(p1 <= mid && p2 <= r){
			temp[i++] = arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
		}
		//上面的循环退出后,把剩余的元素依次填入到temp中
		//以上两个while只有一个会执行
		while(p1 <= mid){
			temp[i++] = arr[p1++];
		}
		while(p2 <= r){
			temp[i++] = arr[p2++];
		}
		//把最终的排序的结果复制给原数组
		for(i = 0;i<temp.length;i++){
			arr[l+i] = temp[i];
		}
	}
	public static void main(String[] args) {
		int[] data = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
		//归并排序
		mergesort(data);
	}
}

二分查找

package com.demo;

import java.util.Arrays;

public class Test {
	 * 二分查找
	 * @param arr
	 * @param left
	 * @param right
	 * @param findVal
	 */
	public static int binarySearch(int[] arr, int left, int right, int findVal){
		if(left > right){//递归退出条件,找不到,返回-1
			return -1;
		}
		int midIndex = (left+right) /2;
		
		if(findVal < arr[midIndex]){//向左递归查找
			return binarySearch(arr, left, midIndex, findVal);
		}else if(findVal > arr[midIndex]){
			return binarySearch(arr, midIndex, right, findVal);
		}else{
			System.out.println("查找下标:"+midIndex);
			return midIndex;
		}
	}
	public static void main(String[] args) {
		int[] data = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
		//二分查找
		binarySearch(data,0,data.length,5);
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值