随笔分类 - java提高篇
摘要:在这篇文章里,我们关注和字符串相关的话题。 在谈论到字符串时,通常情况下,我们是在讨论ASCII码范围内的字符串,即它包括256个字符。在设计字符串相关的算法时,我们需要在时间和空间这两者之间进行权衡。 下面我们来看相关的题目。判断字符串里出现的字符是否是唯一的。 思路:方案一:将字符串转换为字符数组,从第一个字符开始遍历,针对每个字符,判断字符串之前是否出现过该字符,如果出现过,说明该字符在字符串中不是唯一的。对应的空间复杂度O(1),时间复杂度O(n*n)。判断字符串中的字符是否唯一 1 public static boolean Check(String value) 2 { 3 ...
阅读全文
摘要:在这篇文章里,我们主要讨论和递归相关的话题。递归是数据结构中解决复杂问题时非常有效的一种思考方式,对于一个复杂的问题,我们可以从中抽取一个可以通过迭代方式解决的子问题,而子问题是一个容易解决的问题。在使用递归时,有两个问题需要注意:1)抽取递归体;2)确定递归边界条件以及处理方式。 下面我们来看相关的题目。斐波那契数列 我想这应该是最常见的递归的例子了,我们可以使用递归和非递归两种方式来实现它。 首先来看非递归的方式:循环实现斐波那契数列 1 public static int fibo2(int n) 2 { 3 if (n path = new ArrayList(); 6 ...
阅读全文
摘要:生产者-消费者(producer-consumer)问题是一个著名的线程同步问题。它描述的是:有一群生产者线程在生产产品,并将这些产品提供给消费者线程去消费。为使生产者与消费者之间能够并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者将它所生产的产品放入一个缓冲区中;消费者可以从一个缓冲区中取走产品产生消费。尽管所有的生产者线程和消费者线程都是以异步方式运行的,但他们之间必须保持同步,即不允许消费者到一个空缓冲区去消费,也不允许生产者向一个已经被占用的缓冲区投放产品。我把这个问题复杂化,设立m个缓冲池,每个缓冲池都有各自固定的容量,每个生产者或消费者在进行生产消费活动之前,先选择一个
阅读全文
摘要:这一篇主要讲Spring一些基础的内容。 概述 Spring 是一个非常火的框架,尤其是在Web开发领域,和Struts以及Hibernate构成了SSH三剑客。当时Web开发的另一个组合是LAMP,即 Linux+Apache+MySQL+PHP。我在前端方面基本没有实战经验,对js等技术也还是停留在概念和语法方面,所以扬长避短,我对 Spring以及Hibernate特别感兴趣。 当年Spring是作为EJB的“替代者”横空出世的,其创始人Rod Johnson还写了一本《J2EE development without EJB》来推行这个框架,这也是一本关于Spring很经典的书,...
阅读全文
摘要:这篇文章里,我们主要讨论ORM框架,以及在使用上和JDBC的区别。 概述 ORM框架不是一个新话题,它已经流传了很多年。它的优点在于提供了概念性的、易于理解的数据模型,将数据库中的表和内存中的对象建立了很好的映射关系。 我们在这里主要关注Java中常用的两个ORM框架:Hibernate和iBatis。下面来介绍这两个框架简单的使用方法,如果将来有时间,我会深入的写一些更有意思的相关文章。 Hibernate Hibernate是一个持久化框架和ORM框架,持久化和ORM是两个有区别的概念,持久化注重对象的存储方法是否随着程序的退出而消亡,ORM关注的是如何在数据库表和内存对象之间建...
阅读全文
摘要:这篇文章里,我们来讨论一些和JDBC相关的话题。 概述 尽管在实际开发过程中,我们一般使用ORM框架来代替传统的JDBC,例如Hibernate或者iBatis,但JDBC是Java用来实现数据访问的基础,掌握它对于我们理解Java的数据操作流程很有帮助。 JDBC的全称是Java Database Connectivity。 JDBC对数据库进行操作的流程:连接数据库发送数据请求,即传统的CRUD指令返回操作结果集 JDBC中常用的对象包括:ConnectionManagerConnectionStatementCallableStatementPreparedStatementR...
阅读全文
摘要:类的初始化顺序 在Java中,类里面可能包含:静态变量,静态初始化块,成员变量,初始化块,构造函数。在类之间可能存在着继承关系,那么当我们实例化一个对象时,上述各部分的加载顺序是怎样的? 首先来看代码: 1 class Parent 2 { 3 public static StaticVarible staticVarible= new StaticVarible("父类-静态变量1"); 4 public StaticVarible instVarible= new StaticVarible("父类-成员变量1"); 5 6 static 7 ...
阅读全文
摘要:在这一篇文章里,我们关注反射及其相关话题。 反射可以帮助我们查看指定类型中的信息、创建类型的实例,调用类型的方法。我们平时使用框架,例如Spring、EJB、Hibernate等都大量的使用了反射技术。 反射简单示例 下面来演示反射相关的基本操作 首先是基础代码,我们定义一个接口及其实现,作为我们反射操作的目标: 1 interface HelloWorldService 2 { 3 void sayHello(String name); 4 } 5 6 class MyHelloWorld implements HelloWorldService 7 { 8 pub...
阅读全文
摘要:在这篇文章里,我们关注对象序列化。 首先,我们来讨论一下什么是序列化以及序列化的原理;然后给出一个简单的示例来演示序列化和反序列化;有时有些信息是不应该被序列化的,我们应该如何控制;我们如何去自定义序列化内容;最后我们讨论一下在继承结构的场景中,序列化需要注意哪些内容。 序列化概述 序列化,简单来讲,就是以“流”的方式来保存对象,至于保存的目标地址,可以是文件,可以是数据库,也可以是网络,即通过网络将对象从一个节点传递到另一个节点。 我们知道在Java的I/O结构中,有ObjectOutputStream和ObjectInputStream,它们可以实现将对象输出为 二进制流,并从二进...
阅读全文
摘要:在这篇文章里,我们关注Java中的集合(Collection)。集合是编程语言中基础的一部分,Java自JDK早期,就引入了Java Collection Framework。设计JCF的那个人,后来还写了一本书,叫《Effective Java》。 Java中的集合主要集中在2部分,一部分是java.util包中,一部分是java.util.concurrent中,后者是在前者的基础上,定义了一些实现了同步功能的集合。 这篇文章主要关注java.util下的各种集合对象。Java中的集合对象可以粗略的分为3类:List、Set和Map。对应的UML图如下(包括了java.util下大部分..
阅读全文
摘要:在这篇文章里,我们主要讨论如何使用Java实现网络通信,包括TCP通信、UDP通信、多播以及NIO。 TCP连接 TCP的基础是Socket,在TCP连接中,我们会使用ServerSocket和Socket,当客户端和服务器建立连接以后,剩下的基本就是对I/O的控制了。 我们先来看一个简单的TCP通信,它分为客户端和服务器端。 客户端代码如下: 1 import java.net.*; 2 import java.io.*; 3 public class SimpleTcpClient { 4 5 public static void main(String[] args) ...
阅读全文
摘要:这篇文章主要回顾Java中和I/O操作相关的内容,I/O也是编程语言的一个基础特性,Java中的I/O分为两种类型,一种是顺序读取,一种是随机读取。 我们先来看顺序读取,有两种方式可以进行顺序读取,一种是InputStream/OutputStream,它是针对字节进行操作的输入输出流;另外一种是Reader/Writer,它是针对字符进行操作的输入输出流。 下面我们画出InputStream的结构 FileInputStream:操作文件,经常和BufferedInputStream一起使用PipedInputStream:可用于线程间通信ObjectInputStream:可用于对象...
阅读全文
摘要:在这篇文章里,我们关注线程同步的话题。这是比多线程更复杂,稍不留意,我们就会“掉到坑里”,而且和单线程程序不同,多线程的错误是否每次都出现,也是不固定的,这给调试也带来了很大的挑战。 在这篇文章里,我们首先阐述什么是同步,不同步有什么问题,然后讨论可以采取哪些措施控制同步,接下来我们会仿照回顾网络通信时那样,构建一个服务器端的“线程池”,JDK为我们提供了一个很大的concurrent工具包,最后我们会对里面的内容进行探索。 为什么要线程同步? 说到线程同步,大部分情况下, 我们是在针对“单对象多线程”的情况进行讨论,一般会将其分成两部分,一部分是关于“共享变量”,一部分关于“执行步骤”...
阅读全文
摘要:在这篇文章里,我们关注多线程。多线程是一个复杂的话题,包含了很多内容,这篇文章主要关注线程的基本属性、如何创建线程、线程的状态切换以及线程通信,我们把线程同步的话题留到下一篇文章中。 线程是操作系统运行的基本单位,它被封装在进程中,一个进程可以包含多个线程。即使我们不手动创造线程,进程也会有一个默认的线程在运行。 对于JVM来说,当我们编写一个单线程的程序去运行时,JVM中也是有至少两个线程在运行,一个是我们创建的程序,一个是垃圾回收。 线程基本信息 我们可以通过Thread.currentThread()方法获取当前线程的一些信息,并对其进行修改。 我们来看以下代码: 1 Stri...
阅读全文
摘要:在java的线程Thread类中有三个方法,比较容易混淆,在这里解释一下 (1)interrupt:置线程的中断状态 (2)isInterrupt:线程是否中断 (3)interrupted:返回线程的上次的中断状态,并清除中断状态 举个例子:[java] view plaincopyprint?用法:classMyThreadextendsThread{............publicvoidrun(){try{while(!Thread.currentThread().isInterrupted()){//当达到队列容量时,在这里会阻塞//put的内部会调用LockSupport.pa
阅读全文
摘要:首先介绍一下中断概念:举个例子容易理解一点例子:假如你正在给朋友写信,电话铃响了。这时,你放下手中的笔,去接电话。通话完毕,再继续写信。这个例子就表现了中断及其处理过程:电话铃声使你暂时中止当前的工作,而去处理更为急需处理的事情(接电话),把急需处理的事情处理完毕之后,再回头来继续原来的事情。在这个例子中,电话铃声称为“中断请求”,你暂停写信去接电话叫作“中断响应”,接电话的过程就是“中断处理”。interrupt:中断线程如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。如果线程在调用
阅读全文
摘要:先来一个: 取得指定月份的第一天与取得指定月份的最后一天 http://iamin.blogdriver.com/iamin/847990.html/***取得指定月份的第一天**@paramstrdateString*@returnString*/publicStringgetMonthBegin(Stringstrdate){java.util.Datedate=parseFormatDate(strdate);returnformatDateByFormat(date,"yyyy-MM")+"-01";}/***取得指定月份的最后一天**@para
阅读全文