在Java中实现sql的select函数功能
――通过简单的机制实现对象数组或集合的选择,过滤,和排序
David RapPOPOrt
摘要
在“filter collections”中,David Rappoport 讲述了一个过滤集合对象的简单方法。在本文中,他扩展了自己的思想,并展示了怎样实现,如同用sql的select处理关系数据库中的表一样,处理对象数组或集合。他描述了用于选择,过滤,排序队形数组或集合的通用机制。通过这种机制,可以在java的对象数组或集合上实现sql的select函数功能。(2004-11-22)。
假设你希望以表格的形式,如行列的形式,显示数组或集合中的数据,并且希望可以选择显示的属性。另外,你还希望只显示满足一定条件的数据子集,希望用自定义先后顺序的的排序标准对数据排序。
这种类型的功能是sql的select函数提供的:在sql语句中,可以定义数据源(通过from指定);可以定义返回的属性(通过在select后面指定返回列);可以添加条件(where子句);并且可以定义数据显示的顺序(order by子句)。
本文讲述了一些使你能把这些函数使用在任何类型的对象数组和集合上的类和接口。为了实现这些函数功能,机制描述使用了一些设计模式。本文提出的方法有一下一些好处:
1。通过本文的代码(可以下载。。。),你可以在不影响原始数据的前提下,以不同的方式显示数据。
2。排序,过滤和选择制定的属性十分简单,并且结果能很快得到。
3。通过这些类和接口,你可以独立的考虑select语句的各部分,从而可以产生纯净,可复用,可扩展的代码。
但是,你可能也会猜到,机制使用的是通用接口,假如你没有很好的理解它,可能会滥用它。
机制的类和接口
下面的列表给出了我们需要的类和接口的简短说明。后文中,你将看到他们怎么协作,实现设计的功能。每一个类和接口都非常简单,只含有一个到两个函数。
1.接口Invoker包含唯一一个函数:public boolean invoke(Object o)。通过这个接口,可以封装函数调用并返回函数结果。后文你将看到他是怎样使用的。
2.接口Condition也只包含一个函数:public boolean passes(Object o)。使用这个函数,可以检测任意类是否满足任意类型的条件,并返回true或false。同样,你也将在后文中看到本接口的使用。
3.类SelectStatement代表整个select语句,包含select,from,where和order by等子句。
4.类SelectInstrUCtion表示select子句中的一个单一部分,选定列并指定显示时该列的名字。一个完整的select子句用一个SelectInstruction对象数组表示。
5.类OrderInstruction代表order by子句的一个单一部分,整个order by子句由一个OrderInstruction对象数组构成。
6.类Executor执行包含了整个执行逻辑的SelectStatement。
7.类ResultTable代表执行SelectStatement后返回的结果集。它用Object[][]的形式组织结果数据,从而可以轻易的转换和显示数据。
下面将讲述这些类和接口时怎样协作的。类图显示了它们之间的关联。
一个SelectStatement含有一个对象集合或数组(因为集合和数组都只包含统一类型的对象,所以对象的类型没有关系);一个SelectInstruction对象数组;一个Condition对象数组;和一个OrderInstruction对象数组。然后把SelectStatement对象传入Excuter对象,在那里执行这个statement并返回一个ResultTable。
接下来的问题是,SelectInstruction,Condition,OrderInstruction和ResultTable,这些类都是做什么的?我们为什么需要他们?首先,不要一下全看他们,这可能会使你迷惑。一个一个的看,每一个类都是易于理解和使用的。
每一个SelectInstruction代表你希望在结果集中出现的一个列(或者对象的一个属性)。你为他定义一个名字和Invoker。名字将作为列标题出现,Invoker将在集合中的每一个对象上触发。在某个对象上触发后,Invoker在对应列中返回该对象的对应属性。这项函数功能组成了select子句,在这个子句中,可以定义显示的属性,并用as定义列名(如select speed as Max_speed)。注重:你也可以只有一个SelectInstruction,其中的列名串为*。在这种情况下,类中的所有getter()方法都被invoker包覆,其结果都出现在ResultSet中。
每一个Condition代表一个条件,源数据集合中每一个对象都需满足此条件。这个类对应于where子句,通过它可以通过给定的条件排除任意数目的行。注重:假如想要显示全部对象,只需传入空的Condintion[]即可。
每一个OrderInstruction代表一个怎样排序数据的规则,它由一个Invoker和一个Comparator组成。Invoker的invoke(Object o)方法(作用于对象集合中的一个对象时)会返回一个结果,并于作用于集合中其他对象返回的结果进行比较,从而决定结果数据的排序位置。Comparator(假如实现了)比较两个对象在invoke作用下返回的结果。假如comparator没有实现,结果将基于它们各自的compareTo(Object o)方法(假定他们都实现了java.lang,Comparatable)进行比较。