一致性哈希算法与Java实现

一致性哈希算法与Java实现 一致性哈希算法, consistent hashing 概述 引出 登场 改进-虚节点 另一种改进 参考链接: 概述 在维基百科中,是这么定义的 一致哈希是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数 (大小) 的改变平均只需要对 K/n个关键字重新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。 引出 我们在上文中已经介绍了一致性Hash算法的基本优势,我们看到了该算法主要解决的问题是: 当slot数发生变化时,能够尽量少的移动数据。那么,我们思考一下,普通的Hash算法是如何实现?又存在什么问题呢? 那么我们引出一个问题: 假设有1000w个数据项,100个存储节点,请设计一种算法合理地将他们存储在这些节点上。 看一看普通Hash算法的原理: normal_hash 算法的核心计算如下 1 2 3 4 5 6 for item in range(ITEMS): k = md5(str(item)).digest() h = unpack_from(">I", k)[0] # 通过取余的方式进行映射 n = h % NODES node_stat[n] += 1 具体的完整实现请参考normal_hash.py,输出是这样的: Ave: 100000 Max: 100695 (0.69%) Min: 99073 (0.93%) 从上述结果可以发现,普通的Hash算法均匀地将这些数据项打散到了这些节点上,并且分布最少和最多的存储节点数据项数目小于1%。之所以分布均匀,主要是依赖Hash算法 (实现使用的MD5算法) 能够比较随机的分布。 然而,我们看看存在一个问题,由于该算法使用节点数取余的方法,强依赖node的数目,因此,当是node数发生变化的时候,item所对应的node发生剧烈变化,而发生变化的成本就是我们需要在node数发生变化的时候,数据需要迁移,这对存储产品来说显然是不能忍的,我们观察一下增加node后,数据项移动的情况: 1 2 3 4 5 6 7 8 9 for item in range(ITEMS): k = md5(str(item)).digest() h = unpack_from(">I", k)[0] # 原映射结果 n = h % NODES # 现映射结果 n_new = h % NEW_NODES if n_new != n: change += 1 详细实现代码在normal_hash_add.py输出是这样的: Change: 9900989 (99.01%) 翻译一下就是,如果有100个item,当增加一个node,之前99%的数据都需要重新移动。 这显然是不能忍的,普通哈希算法的问题我们已经发现了,如何对其进行改进呢?没错,我们的一致性哈希算法闪亮登场。 登场 我们上节介绍了普通Hash算法的劣势,即当node数发生变化 (增加、移除) 后,数据项会被重新"打散",导致大部分数据项不能落到原来的节点上,从而导致大量数据需要迁移。 那么,一个亟待解决的问题就变成了: 当node数发生变化时,如何保证尽量少引起迁移呢?即当增加或者删除节点时,对于大多数item,保证原来分配到的某个node,现在仍然应该分配到那个node,将数据迁移量的降到最低。 一致性Hash算法的原理是这样的: consist_hash 1 2 3 4 5 6 7 8 9 10 for n in range(NODES): h = _hash(n) ring.append(h) ring.sort() hash2node[h] = n for item in range(ITEMS): ...

2012-05-28 · 3 min · 617 words · -

java5

java5 可变参数, 变长参数 在 Java 5 中提供了变长参数,允许在调用方法时传入不定长度的参数。变长参数是 Java 的一个语法糖,本质上还是基于数组的实现: public class Varargs { public static void test(String... args) { for(String arg : args) { System.out.println(arg); } } public static void main(String[] args) { test();//0个参数 test("a");//1个参数 test("a","b");//多个参数 test(new String[] {"a", "b", "c"});//直接传递数组 } }

2012-03-28 · 1 min · 43 words · -

CDI

http://www.infoq.com/cn/articles/cf-javaone-2011-cdi-google-dart CDI 对于依赖注入的概念,相信很多开发人员都不陌生。一个组件在运行过程中会依赖其他组件提供的功能。传统的做法是由组件本身负责查找所需的依赖对象。这种方式会造成组件之间的紧耦合,不利于组件的维护和更新。依赖注入的做法则是由组件以声明式的方式表明其依赖关系,由框架在运行时把所需的组件的Java对象注入到当前组件中。相对于Java SE来说,依赖注入的概念对于Java EE更加适用。Java EE中的很多资源和服务都是由容器来负责管理的。对于单个应用来说,查找由容器负责管理的组件并不是一件容易的事情。更好的做法是由应用来声明所需的资源和服务,由容器负责注入到应用中。通过这种方式,容器也可以更好的对资源和服务进行管理。以数据库连接为例,传统的做法需要由应用本身加载相关驱动并创建数据库连接,以及在适当的时候进行释放。而使用容器管理并注入依赖的做法,则减轻了应用开发人员的工作量。 Java EE 5中添加了对依赖注入的有限支持。通过注解可以往容器管理的对象中注入资源的对应对象。Java EE 6中把依赖注入的概念更进一步,即引入了JSR 299 (Contexts and Dependency Injection for the Java EE platform)规范,简称CDI。CDI规范吸收了来自Spring IoC容器、JBoss Seam和Google Guice的最佳实践,并与Java EE开发的实际需要相结合。正如CDI的字面含义一样,CDI中的两个核心功能是上下文信息 (context) 和依赖注入。这两个功能的结合点是Java中基本的组件模型bean。在CDI中,bean 定义了应用的状态和逻辑,并由容器来进行管理。每个被管理的bean都有定义好的绑定到特定上下文的作用域和生命周期。当需要注入或访问bean时,容器会从作用域对应的上下文中获取。当作用域失效时,对应上下文中所有的对象都会被删除。CDI中的每个bean都可以作为依赖注入时的目标。 CDI中预定义了一些常用的作用域。默认的作用域是Dependent,表示只对被注入的对象生效。作用域ApplicationScoped表示应用的全局作用域,用来创建全局唯一的对象。RequestScoped和SessionScoped则与HTTP相关,分别表示HTTP请求和HTTP会话。ConversationScoped是由应用自定义生命周期长短的作用域,可以用来实现跨多页面的工作流。如下面代码中的OrderProcessor类只存活在HTTP请求中,并且依赖OrderDao接口的实现。容器会在运行时查找到OrderDao接口的实现对象,并注入到OrderProcessor类的对象中。 @Named @RequestScoped public class OrderProcessor { @Inject private OrderDao orderDao; } 通常的依赖注入方式是在代码中只依赖接口,由容器在运行时选择合适的实现类的对象来进行注入。如果接口只有一个实现类,则不需要额外的声明。如果接口有不同的实现,则需要使用限定符 (qualifier) 来声明具体使用的实现,否则容器无法做出正确的选择。CDI的一个特点是限定符不是普通的字符串,而是类型安全的注解。 通过Qualifier元注解可以创建新的限定符注解。如下面的代码创建了一个新的限定符注解InMemory。 @Qualifier @Retention(RUNTIME) @Target({TYPE}) public @interface InMemory {} 该注解可以添加在OrderDao接口的实现上。 @InMemory public class InMemoryOrderDao implements OrderDao { } 如果在测试时,希望使用简单的基于内存的存储实现,可以使用InMemory注解来声明。这样容器在注入时会使用InMemoryOrderDao类的对象。 @Named @RequestScoped public class OrderProcessor { @Inject @InMemory private OrderDao orderDao; } ...

2012-03-26 · 2 min · 276 words · -

Spring的静态工厂方法

Spring的静态工厂方法 http://blog.csdn.net/chensugang/article/details/3357593 上一次写了一篇关于DI的三种方式,其中里面介绍了构造方法的方式,今天学习了一种替代构造器的方法,这就是静态工厂方法来返回对象,下面来看一下静态工厂方法的实现。 静态工厂方法: LoginAction类: package com.spring.test.di; public class LoginAction { private Logic logic; private LoginAction(Logic logic){ this.logic = logic; } public static LoginAction createInstance(Logic logic){ LoginAction loginAction = new LoginAction (logic); return loginAction; } public void execute() { String name = logic.getName(); System.out.print(“My Name Is " + name); } } 注意: 这里使用的构造方法是一个私有方法,createInstance这个就是我们的静态工厂方法 Logic接口: package com.spring.test.di; public interface Logic { public String getName(); } 这里只是做为一个简单的例子,所以我们在该接口中只有一个方法,并且在该接口的实现方法也超级简单 Logic接口实现: package com.spring.test.di; public class LogicImpl implements Logic{ public String getName(){ return “fengyun”; ...

2012-03-26 · 1 min · 133 words · -

static factory method

static factory method 创建类的实例的最常见的方式是用new语句调用类的构造方法。在这种情况下,程序可以创建类的任意多个实例,每执行一条new语句,都会导致Java虚拟机的堆区中产生一个新的对象。假如类需要进一步封装创建自身实例的细节,并且控制自身实例的数目,那么可以提供静态工厂方法。 例如Class实例是Java虚拟机在加载一个类时自动创建的,程序无法用new语句创建java.lang.Class类的实例,因为Class类没有提供public类型的构造方法。为了使程序能获得代表某个类的Class实例,在Class类中提供了静态工厂方法forName(String name),它的使用方式如下: Class c=Class.forName( “Sample “); //返回代表Sample类的实例 静态工厂方法与用new语句调用的构造方法相比,有以下区别。 (1) 构造方法的名字必须与类名相同。这一特性的优点是符合Java语言的规范,缺点是类的所有重载的构造方法的名字都相同,不能从名字上区分每个重载方法,容易引起混淆。 静态工厂方法的方法名可以是任意的,这一特性的优点是可以提高程序代码的可读性,在方法名中能体现与实例有关的信息。例如例程11-5的Gender类有两个静态工厂方法: getFemale()和getMale()。 例程11-5 Gender.java public class Gender{ private String description; private static final Gender female=new Gender( “女 “); private static final Gender male=new Gender( “男 “); private Gender(String description){this.description=description;} public static Gender getFemale(){ return female; } public static Gender getMale(){ return male; } public String getDescription(){return description;} } 这一特性的缺点是与其他的静态方法没有明显的区别,使用户难以识别类中到底哪些静态方法专门负责返回类的实例。为了减少这一缺点带来的负面影响,可以在为静态工厂方法命名时尽量遵守约定俗成的规范,当然这不是必需的。目前比较流行的规范是把静态工厂方法命名为valueOf或者getInstance。 l valueOf: 该方法返回的实例与它的参数具有同样的值,例如: Integer a=Integer.valueOf(100); //返回取值为100的Integer对象 从上面代码可以看出,valueOf()方法能执行类型转换操作,在本例中,把int类型的基本数据转换为Integer对象。 l getInstance: 返回的实例与参数匹配,例如: ...

2012-03-26 · 2 min · 265 words · -

java中Class.getResource用法

java中Class.getResource用法 用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还是掌握颇浅,用起来感觉颇深,大常最经常用的,就是用JAVA的File类,如要取得c:/test.txt文件,就会这样用File file = new File(“c:/test.txt”);这样用有什么问题,相信大家都知道,就是路径硬编码,对于JAVA精神来说,应用应该一次成型,到处可用,并且从现实应用来讲,最终生成的应用也会部署到Windows外的操作系统中,对于linux来说,在应用中用了c:/这样的字样,就是失败,所以,我们应该尽量避免使用硬编码,即直接使用绝对路径。 在Servlet应用中,有一个getRealPath(String str)的方法,这个方法尽管也可以动态地获得文件的路径,不秘直接手写绝对路径,但这也是一个不被建议使用的方法,那么,我们有什么方法可以更好地获得文件呢? 那就是Class.getResource()与Class.getResourceAsStream()方法,但很多人还是不太懂它的用法,因为很多人 (比如不久前的我) 都不知道应该传怎么样的参数给它,当然,有些人己经用得如火纯青,这些人是不需要照顾的,在此仅给不会或者还不是很熟的人解释一点点。 比如我们有以下目录 |-project |-src |-javaapplication |-Test.java |-file1.txt |-file2.txt |-build |-javaapplication |-Test.class |-file3.txt |-file4.txt 在上面的目录中,有一个src目录,这是JAVA源文件的目录,有一个build目录,这是JAVA编译后文件(.class文件等) 的存放目录 那么,我们在Test类中应该如何分别获得 file1.txt file2.txt file3.txt file4.txt这四个文件呢? 首先讲file3.txt与file4.txt file3.txt: 方法一: File file3 = new File(Test.class.getResource(“file3.txt”).getFile()); 方法二: File file3 = new File(Test.class.getResource("/javaapplication/file3.txt").getFile()); 方法三: File file3 = new File(Test.class.getClassLoader().getResource(“javaapplication/file3.txt”).getFile()); file4.txt: 方法一: File file4 = new File(Test.class.getResource("/file4.txt").getFile()); 方法二: File file4 = new File(Test.class.getClassLoader().getResource(“file4.txt”).getFile()); 很好,我们可以有多种方法选择,但是file1与file2文件呢?如何获得? 答案是,你只能写上它们的绝对路径,不能像file3与file4一样用class.getResource()这种方法获得,它们的获取方法如下 假如整个project目录放在c:/下,那么file1与file2的获取方法分别为 file1.txt 方法一: File file1 = new File(“c:/project/src/javaapplication/file1.txt”); ...

2012-01-02 · 1 min · 142 words · -

Collection, Array, Vector, ArrayList, List, LinkedList

Collection, Array, Vector, ArrayList, List, LinkedList array(数组)和Vector是十分相似的Java构件 (constructs) ,两者全然不同,在选择使用时应根据各自的功能来确定。 数组 Array Java arrays 的元素个数不能下标越界,从很大程度上保证了Java程序的安全性,而其他一些语言出现这一问题时常导致灾难性的后果。 Array 可以存放Object和基本数据类型,但创建时必须指定数组的大小,并不能再改变。值得注意的是: 当Array中的某一元素存放的是Objrct reference 时,Java不会调用默认的构造函数,而是将其初值设为null,当然这跟Java对各类型数据赋默认值的规则是一样的,对基本数据类型同样适用。 线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类。 Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素 (Elements) 。一些 Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类, Java SDK提供的类都是继承自Collection的"子接口"如List和Set。 所有实现Collection接口的类都必须提供两个标准的构造函数: 无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的 Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。 如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下: Iterator it = collection.iterator(); // 获得一个迭代子 while(it.hasNext()) { Object obj = it.next(); // 得到下一个元素 } 由Collection接口派生的两个接口是List和Set。 List接口 List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引 (元素在List中的位置,类似于数组下标) 来访问List中的元素,这类似于Java的数组。 和下面要提到的Set不同,List允许有相同的元素。 除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。 实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。 LinkedList类 LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈 (stack) ,队列 (queue) 或双向队列 (deque) 。 注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List: List list = Collections.synchronizedList(new LinkedList(…)); ...

2011-11-09 · 3 min · 469 words · -

Java EE

Java EE Java EE,Java2平台企业版 (Java 2 Platform Enterprise Edition) ,是Sun公司为企业级应用推出的标准平台。Java平台共分为三个主要版本Java EE、Java SE和Java ME。 Sun公司在1998年发表JDK1.2版本的时候,使用了新名称Java 2 Platform,即"Java2平台",修改后的JDK称为Java 2 Platform Software Developing Kit,即J2SDK。并分为标准版 (Standard Edition,J2SE) ,企业版 (Enterprise Edition,J2EE) ,微型版 (MicroEdition,J2ME) 。J2EE便由此诞生。 2005年6月,JavaOne大会召开,SUN公司发布Java SE 6。此时,Java的各种版本已经更名并取消其中的数字"2": J2EE更名为Java EE, J2SE更名为Java SE,J2ME更名为Java ME。 随着Java技术的发展,Java EE平台得到了迅速的发展,成为Java语言中最活跃的体系之一。现如今,Java EE不仅仅是指一种标准平台,它更多的表达着一种软件架构和设计思想。 Java EE是一系列技术标准所组成的平台,包括: JDBC - Java数据库联接 (Java Database Connectivity) JSP - Java服务器页面 (Java Server Pages) JSF - Java Server Faces JSTL - Java服务器页面标准标签库 (Java Server Pages Standard Tag Library) WS - Web Services ...

2011-10-16 · 1 min · 186 words · -

Servlet

Servlet servlet的由来 自从计算机软件开发进入网络时代,就开始涉及到通讯问题。在客户/服务器 (C/S) 时期,每个软件都有自己的客户端和服务器端软件。并且客户端和服务器端之间的通讯协议差别也很大。后来随着互联网的发展,基于浏览器/服务器(B/S)的应用逐渐成为主流,通讯协议也统一到HTTP协议。但是,在HTTP协议之上,如何处理来自客户端的请求信息,以及如何对请求进行回应,则经历了很长时间也没有统一下来。目前,对于这个问题的解决方案主要有两种,一个是CGI,另一个是Servlet。 servlet是在服务器上运行的小程序。这个词是在Java applet的环境中创造的,Java applet是一种当作单独文件跟网页一起发送的小程序,它通常用于在客户端运行,结果得到为用户进行运算或者根据用户互作用定位图形等服务。服务器上需要一些程序,常常是根据用户输入访问数据库的程序。这些通常是使用公共网关接口 (CGI(Common Gateway Interface)) 应用程序完成的。然而,在服务器上运行Java,这种程序可使用Java编程语言实现。在通信量大的服务器上,servlet的优点在于它们的执行速度更快于CGI程序。各个用户请求被激活成单个程序中的一个线程,而无需创建单独的进程,这意味着服务器端处理请求的系统开销将明显降低。最早支持Servlet技术的是JavaSoft的Java Web Server。此后,一些其它的基于Java的WebServer开始支持标准的ServletAPI。 Servlet最初是在1995年由James Gosling 提出的,因为使用该技术需要复杂的Web服务器支持,所以当时并没有得到重视,也就放弃了。后来随着Web应用复杂度的提升,并要求提供更高的并发处理能力,Servlet被重新捡起,并在Java平台上得到实现,现在提起Servlet,指的都是Java Servlet。Java Servlet要求必须运行在Web服务器当中,与Web服务器之间属于分工和互补关系。确切的说,在实际运行的时候Java Servlet与Web服务器会融为一体,如同一个程序一样运行在同一个Java虚拟机 (JVM) 当中。与CGI不同的是,Servlet对每个请求都是单独启动一个线程,而不是进程。这种处理方式大幅度地降低了系统里的进程数量,提高了系统的并发处理能力。另外因为Java Servlet是运行在虚拟机之上的,也就解决了跨平台问题。 在Servlet出现之后,随着使用范围的扩大,人们发现了它的一个很大的一个弊端。那就是为了能够输出HTML格式内容,需要编写大量重复代码,造成不必要的重复劳动。为了解决这个问题,基于Servlet技术产生了Java Server Pages (JSP) 。 Servlet和JSP两者分工协作,Servlet侧重于解决运算和业务逻辑问题,JSP则侧重于解决展示问题。Servlet与JSP一起为Web应用开发带来了巨大的贡献,后来出现的众多Java Web应用开发框架都是基于这两种技术的,更确切的说,都是基于Servlet技术的。 Servlet与Web容器之间的关系 Java是一种动态加载和运行的语言。也就是说当应用程序持有一个类的地址 (CLASSPATH) 和名称 (包名和类名) 的情况下,可以在程序运行期间任何时候加载这个类,并创建和使用该类的对象。Servlet就是基于这个机制与Web容器融合在一起的。目前已知的所有支持Java Servlet的Web容器都是采用Java开发的。当Web容器接收到来自客户端的请求信息之后,会根据URL中的Web元件地址信息到Servlet队列中查找对应的Servlet对象,如果找到则直接使用,如果没有找到则加载对应的类,并创建对象。也就是说,Servlet对象是在第一次被使用的时候才创建的,并且一旦创建就会被反复使用,不再创建新的对象。所有创建出的Servlet对象会在Web服务器停止运行的时候统一进行垃圾回收。 为了解决客户端请求地址与 Servlet之间对应关系问题,Web容器需要一个用来描述这种对应关系的文件,一般是web.xml文件。如果一个Web应用程序中存在很多个Servlet,那么web.xml会变得非常庞大。在Servlet 3.0规范推出之后,允许在Servlet代码中使用声明式语法(annotation)来代替web.xml中的描述信息,这才让web.xml瘦身下来. Servlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。 它担当客户请求 (Web浏览器或其他HTTP客户程序) 与服务器响应 (HTTP服务器上的数据库或应用程序) 的中间层。 Servlet是位于Web 服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机。 Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容。这个过程为: 客户端发送请求至服务器端; 服务器将请求信息发送至Servlet ; Servlet生成响应内容并将其传给Server。响应内容动态生成,通常取决于客户端的请求; 服务器将响应返回给客户端; Servlet看起来像是通常的Java程序。Servlet导入特定的属于Java ServletAPI的包。因为是对象字节码,可动态地从网络加载,可以说Servlet对Server就如同Applet对Client一样,但是,由于Servlet运行于Server中,它们并不需要一个图形用户界面。从这个角度讲,Servlet也被称为FacelessObject。 一个servlet就是Java编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过"请求-响应"编程模型来访问的应用程序。虽然servlet可以对任何类型的请求产生响应,但通常只用来扩展Web服务器的应用程序。 目前最新版本为3.0草案命名: Server + Applet =Servlet 意为服务器端的小程序 Servlet生命周期 装载Servlet。这项操作一般是动态执行的。然而,Server通常会提供一个管理的选项,用于在Server启动时强制装载和初始化特定的Servlet。 Server创建一个Servlet的实例 Server调用Servlet的init()方法 一个客户端的请求到达Server Server创建一个请求对象 Server创建一个响应对象 Server激活Servlet的service()方法,传递请求和响应对象作为参数 service()方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息 service()方法使用响应对象的方法,将响应传回Server,最终到达客户端。service()方法可能激活其它方法以处理请求,如doGet()或doPost()或程序员自己开发的新的方法。 对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用init()方法。一般Servlet只初始化一次(只有一个对象),当Server不再需要Servlet时(一般当Server关闭时),Server调用Servlet的Destroy()方法。 ...

2011-10-16 · 3 min · 481 words · -

javaEE

javaEE 今天的程序员越来越认识到我们需要高性能、安全和可靠的服务器端技术来开发分布式的、事务性的和可移植的应用程序。在信息化的世界里,企业级应用通常需要更高的性能,更少的费用和更少的资源。 在 Java 平台中,使用 Java EE 来开发 Java 企业程序相当容易和高效。Java EE 平台为程序员提供了强大的 API,目的是为了缩短开发周期,降低应用程序复杂度,提高应用程序性能。 Java EE 通过 JCP (Java 执行委员会) 进行开发,JCP 是一个开放的国际组织,其中的成员包括 Oracle、IBM、Apache 等,JCP 负责所有的 Java 技术。其中的专家组会提交 Java EE 相关的 JSR (Java 标准请求) 。JCP 需要确保 Java 标准的稳定和跨平台兼容性。 Java EE 6 平台最主要的目标是为大量的 Java EE 组件提供共同的基础。程序员可以更多地使用 annotation (元数据注释) 来代替 XML 配置文件,更多地使用 POJO 来进行来发,并且应用程序的打包部署过程也更加简单。 Java EE 6 包括了以下新的特性: Profiles 我们知道 Java EE 规范本身相当庞大,如果我们需要开发的应用使用不到这么多的 Java EE 技术,那么完全没有必要引入这么多的 Java EE 技术到我们的应用程序中去。例如,如果要构建一个类似于 SOA 的应用程序,会用到消息,事务,持久化以及 Web Services ,但犯不着需要使用像 JSP 或 JSF 这类的展示层技术。 ...

2011-09-23 · 2 min · 348 words · -

Derby

Derby Apache Derby, an Apache DB subproject, is an open source relational database implemented entirely in Java and available under the Apache License, Version 2.0. Some key advantages include: Derby has a small footprint - about 2.6 megabytes for the base engine and embedded JDBC driver. Derby is based on the Java, JDBC, and SQL standards. Derby provides an embedded JDBC driver that lets you embed Derby in any Java-based solution. ...

2011-09-22 · 2 min · 271 words · -

java 数组 list set, 数组转set

java 数组 list set, 数组转set http://jerval.iteye.com/blog/1001643 //数组->Set String[] strs = {“AA”,“BB”}; Set set2 = new HashSet(Arrays.asList(strs)); System.out.println(set2); //Set->数组 Set set3 = new HashSet(Arrays.asList(“PP”,“OO”)); String[] strSet = new String[set3.size()]; set3.toArray(strSet); System.out.println(Arrays.toString(strSet)); List(interface): 次序是List最重要的特点;它确保维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(只推荐LinkedList使用)。一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和删除元素。 ArrayList: 由数组实现的List。它允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和删除元素,因为这比LinkedList开销要大很多。 LinkedList: 对顺序访问进行了优化,向List中间插入与删除得开销不大,随机访问则相对较慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。 #################################### Set(interface): 存入Set的每个元素必须是唯一的,因为Set不保存重复元素。加入Set的Object必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。 HashSet: 为快速查找而设计的Set。存入HashSet的对象必须定义hashCode()。采用散列函数对元素进行排序,这是专门为快速查询而设计的; TreeSet: 保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。TreeSet采用红黑树的数据结构进行排序元素; LinkedHashSet: 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。LinkedHashSet内部使用散列以加快查询速度,同时使用链表维护元素的次序,使得看起来元素是以插入的顺序保存的。 需要注意的是,生成自己的类时,Set需要维护元素的存储顺序,因此要实现Comparable接口并定义compareTo()方法。

2011-09-08 · 1 min · 46 words · -

函数式编程, Functional Programming

函数式编程, Functional Programming 函数式编程已经存在了很长了时间,早在50年代 Lisp 编程语言的介绍中就有提过。如果你有关注近两年里内热门的 Clojure,Scala,Erlang,Haskell,Elixir 等语言的话,其中都有函数式编程的概念。 函数式编程的简要历史 正如我们所说的,早在50年代函数式编程开始之前,Lisp 语言就已经在 IBM 700/7000 系列的科学计算机上运行了。Lisp 引入了很多与我们现在的函数式编程有关的示例与功能,我们甚至可以称 Lisp 是所有函数式编程语言的鼻祖。 这也是函数式编程中最有趣的方面,所有函数式编程语言都是基于相同的 λ演算,这种简单数学基础。 λ演算是图灵完备的,它是一种通用的计算模型,可用于模拟任何一台单带图灵机。它名字中的希腊字母 lambda (λ),被使用在了 lambda 表达式和 lambda 项绑定函数中的变量中。 λ演算是一个极其简单但又十分强大的概念。它的核心主要有两个概念: 函数的抽象,通过引入变量来归纳得出表达式; 函数的应用,通过给变量赋值来对已得出的表达式进行计算; 什么是函数式编程 什么是函数式编程?它是一种编程范式,即一切都是数学函数。函数式编程语言里也可以有对象,但通常这些对象都是恒定不变的 —— 要么是函数参数,要什么是函数返回值。函数式编程语言里没有 for/next 循环,因为这些逻辑意味着有状态的改变。相替代的是,这种循环逻辑在函数式编程语言里是通过递归、把函数当成参数传递的方式实现的。 函数式编程单看上面的理论无疑是无法理解的,所以,需要通过它的一些特点来感受什么是函数式编程 函数是"第一等公民" 所谓"第一等公民" (first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。 举例来说,下面代码中的print变量就是一个函数,可以作为另一个函数的参数。 只用"表达式",不用"语句" “表达式” (expression)是一个单纯的运算过程,总是有返回值;“语句” (statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。 原因是函数式编程的开发动机,一开始就是为了处理运算 (computation),不考虑系统的读写 (I/O)。“语句"属于对系统的读写操作,所以就被排斥在外。 当然,实际应用中,不做I/O是不可能的。因此,编程过程中,函数式编程只要求把I/O限制到最小,不要有不必要的读写行为,保持计算过程的单纯性。 没有"副作用” 所谓"副作用" (side effect),指的是函数内部与外部互动 (最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。 函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值. 不修改状态 上一点已经提到,函数式编程只是返回新的值,不修改系统变量。因此,不修改变量,也是它的一个重要特点。 在其他类型的语言中,变量往往用来保存"状态" (state)。不修改变量,意味着状态不能保存在变量中。函数式编程使用参数保存状态,最好的例子就是递归。 引用透明 引用透明 (Referential transparency),指的是函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。 OO (object oriented,面向对象)是抽象数据,FP (functional programming,函数式编程)是抽象行为。 在java中,函数式编程是通过lambda表达式实现的。 lambada表达式 基本表达形式如下: ...

2011-08-28 · 1 min · 110 words · -

java gc监控, jstat

java gc监控, jstat jstat -<option> [-t] [-h] <vmid> [<interval> [<count>]] jstat -gc -h3 <jvm PID> 3000 -1 # -gc 显示gc的信息,查看gc的次数,及时间。 # -h: 即-h跟数字,代表隔几行显示标题 # interval: 毫秒,代表监控间隔时间段,默认毫秒做单位 # count: 代表取数次数 Jstat在分析java的内存GC时的应用 jstat可以查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。 参数: jstat -class pid: Statistics on the behavior of the class loader. 显示加载class的数量,及所占空间等信息; jstat -compiler pid: Statistics of the behavior of the HotSpot Just-in-Time compiler.显示VM实时编译的数量等信息; jstat -gc pid: Statistics of the behavior of the garbage collected heap.可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。 jstat -gccapacity:可以显示,VM内存中三代 (young,old,perm) 对象的使用和占用大小,如: PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OC是old内纯的占用量。 ...

2011-08-09 · 2 min · 329 words · -