Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 290|回复: 0

[Java基础知识]过滤器集合

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-2 11:46:23 | 显示全部楼层 |阅读模式
    过滤器集合        
                                   --一个实现过滤器集合的简易的通用机制
    By David Rappoport, javaWorld.com, 10/18/04

         经常地,你必须遍历一个对象集合并基于一些条件(criteria)来过滤它们。JDK提供了有用的机制来排序集合,即Comparator接口。然而,JDK缺少过滤集合的机制。

         这篇文章描述了一个仅由一个类和一个接口组成的简单机制,它允许你快速和灵活地过滤集合。当搜索一个集合时,该机制提供了与SQL中的select语句相同的功能。它的隐含的概念是,在遍历集合和过滤集合中的对象时,达到职责的分离。
         这里提出的方法有下面的优点:
         1、一个核心的过滤器组件的复用产生更清晰的代码。
         2、通用过滤组件的复用产生更免于错误的代码。
         3、从过滤逻辑中分离出迭代逻辑使你任意地增加和删除过滤器而不影响到其他代码。
         4、对于大集合和多个criteria能够获得性能提高。
    问题    想象一个搜索接口(mask),用户通过选择众多不同的条件(criteria)来搜索汽车。为了简单地完成这个任务,开发者必须多次遍历(iterate)集合。在每一次遍历中,他必须对集合中的每一个对象执行一定的逻辑来确定该对象是否满足条件(criteria)。通常,这个过程的结果是很难阅读和维护的凌乱的代码。
    解决办法     我们定义了一个类CollectionFilter和一个接口FilterCriteria。FilterCriteria仅仅定义了一个方法:public boolean passes(Object o)。这个方法中,集合中的一个对象必须通过一定的测试。如果它通过测试,该方法返回true,否则返回false。CollectionFilter接收一些FilterCriteria作为输入。然后你能调用public void filter(Collection)方法,该方法应用了集合中所有的FilterCriteria,并删除集合中没有通过所有FilterCriteria的任何对象。

         CollectionFilter类也定义了public Collection filterCopy(Collection)方法,它完成和filter(Collection)方法相同的任务,但对原始的过滤器做了复制。代码如下(译者添加):




      
    package
      com.drap.filter;


    /**

      * <p>Title: FilterCriteria</p>
      * <p>Description: A FilterCriteria is added to the CollectionFilter to filter
      * all the objects in the collection. </p>
      *
    @author
      David Rappoport
      *
    @version
      1.0
      
    */



    public
      
    interface
      FilterCriteria {

         
    /**

          * Implement this method to return true, if a given object in the collection
          * should pass this filter.
          * Example: Class Car has an attribute color (String). You only want Cars
          * whose color equals "red".
          * 1) Write the FilterCriteria implementation:
          * class RedColorFilterCriteria implements FilterCriteria{
          *     public boolean passes(Object o){
          *         return ((Car)o).getColor().equals("red");
          *     }
          * }
          * 2) Then add this FilterCriteria to a CollectionFilter:
          * CollectionFilter filter = new CollectionFilter();
          * filter.addFilterCriteria(new ColorFilterCriteria());
          * 3) Now filter:
          * filter.filter(carCollection);
          *
    @param
      o
          *
    @return

          
    */

         
    public
      
    boolean
      passes(Object o);
    }



      
    package
      com.drap.filter;


    import
      java.lang.reflect.
    *
    ;


    import
      java.util.
    *
    ;


    /**


      * <p>Title: CollectionFilter</p>

      * <p>Description: </p>

      *
    @author
      David Rappoport

      *
    @version
      1.0

      
    */



    public
      
    class
      CollectionFilter
    implements
      java.io.Serializable {


         
    private
      ArrayList allFilterCriteria
    =
      
    new
      ArrayList();

         
    /**


          * Adds a FilterCriteria to be used by the filter

          *
    @param
      filterCriteria

          
    */


         
    public
      
    void
      addFilterCriteria(FilterCriteria filterCriteria){

             allFilterCriteria.add(filterCriteria);

         }

         
    /**


          * Starts the filtering process. For each object in the collection,

          * all FilterCriteria are called. Only if the object passess

          * all FilterCriteria it remains in the collection. Otherwise, it is removed.

          *
    @param
      collection

          
    */


         
    public
      
    void
      filter(Collection collection){

             
    if
    (collection
    !=
      
    null
    ){

                 Iterator iter
    =
      collection.iterator();

                
    while
    (iter.hasNext()){

                     Object o
    =
      iter.next();

                     
    if
    (
    !
    passesAllCriteria(o)){

                         iter.remove();

                     }

                 }

             }

         }

         
    /**


          * This method does the same as the filter method. However, a copy of

          * the original collection is created and filtered. The original collection

          * remains unchanged and the copy is returned. Only use this method

          * for collection classes that define a default constructor

          *
    @param
      inputCollection

          *
    @return
      a filtered copy of the input collection

          
    */


         
    public
      Collection filterCopy(Collection inputCollection){

             Collection outputCollection
    =
      
    null
    ;

             
    if
    (inputCollection
    !=
      
    null
    ){

                 outputCollection
    =
      (Collection)createObjectSameClass(inputCollection);

                 outputCollection.addAll(inputCollection);

                 Iterator iter
    =
      outputCollection.iterator();

                
    while
    (iter.hasNext()){

                     Object o
    =
      iter.next();

                     
    if
    (
    !
    passesAllCriteria(o)){

                         iter.remove();

                     }
                 }

             }

             
    return
      outputCollection;

         }

         
    /**


          * Makes sure the specified object passes all FilterCriteria"s passes method.

          *
    @param
      o

          *
    @return


          
    */


         
    private
      
    boolean
      passesAllCriteria(Object o){

             
    for
    (
    int
      i
    =
      
    0
    ; i
    <
      allFilterCriteria.size(); i
    ++
    ){

                 FilterCriteria filterCriteria
    =
      (FilterCriteria)allFilterCriteria.get(i);

                
    if
    (
    !
    filterCriteria.passes(o)){

                     
    return
      
    false
    ;
                 }

             }

             
    return
      
    true
    ;

         }


         
    /**


          * Call the no arguments constructor of the object passed

          *
    @param
      object

          *
    @return


          
    */


         
    public
      Object createObjectSameClass(Object object){

             Class[] NO_ARGS
    =
      
    new
      Class[
    0
    ];

             Object sameClassObject
    =
      
    null
    ;

             
    try
    {

                
    if
    (object
    !=
      
    null
    ){

                     Constructor constructor
    =
      object.getClass().getConstructor(NO_ARGS);

                     sameClassObject
    =
      constructor.newInstance(NO_ARGS);

                 }

             }
    catch
    (IllegalAccessException e){

                
    //
    @todo do something



             }
    catch
    (NoSuchMethodException e){

                
    //
    @todo do something



             }
    catch
    (InstantiationException e){

                
    //
    @todo do something



             }
    catch
    (Exception e){

                
    //
    @todo do something



             }

             
    return
      sameClassObject;

         }


    }



         就是这样了!
         就像你可能已经注意到了,这个解决方法使用了职责链设计模式的部分思想并应用它们到集合中。
         下面的类图说明了类和接口及它们之间的关系。








    简单的例子 让我们看一个例子:类car有三个属性:String color, double maxSpeed, boolean fourWheelDrive。
    你的应用程序允许基于这些条件来搜索cars:用户能输入她喜欢的颜色,她也能提供她想要car拥有的最大速度,及car是否支持four-wheel驱动。
         我们现在创建三个过滤器类来满足用户选择的条件。
         1、FilterCriteria的实现如下:



      
    class
      ColorFilterCriteria
    implements
      FilterCriteria{
         
    private
      String color;
         
    public
      
    boolean
      passes(Object o){
             
    return
      ((Car)o).getColor().equals(color);
         }
    }

    class
      MaxSpeedFilterCriteria
    implements
      FilterCriteria{
         
    private
      
    int
      maxSpeed;
         
    public
      
    boolean
      passes(Object o){
             
    return
      ((Car)o).getMaxSpeed()
    >=
      maxSpeed;
         }
    }

    class
      FourWheelDriveFilterCriteria
    implements
      FilterCriteria{
         
    private
      
    boolean
      fourWheelDriveRequired;
         
    private
      
    boolean
      fourWheelDriveAllowed;
         
    public
      
    boolean
      passes(Object o){
             
    return
      fourWheelDriveRequired
    ?
    ((Car)o).isFourWheelDrive():fourWheelDriveAllowed
    ?
    true
    :
    !

         ((Car)o).isFourWheelDrive();
         }
    }

         2、添加这些FilterCriteria到CollectionFilter中。




      
    CollectionFilter collectionFilter
    =
      
    new
      CollectionFilter();
    filter.addFilterCriteria(
    new
      ColorFilterCriteria(color));
    filter.addFilterCriteria(
    new
      MaxSpeedFilterCriteria(maxSpeed));
    filter.addFilterCriteria(
    new
      FourWheelDriveFilterCriteria(fourWheelDriveRequired, fourWheelDriveAllowed));

         3、调用过滤方法:




      
    collectionFilter.filter(carCollection);
         4、测试代码。 请下载

    技术的使用(Technicalities) 正如你可能意识到的,和Comparator接口中的compare(Object o1, Object o2)方法相似,FilterCriteria接口中的passes(Object o)方法接收任何类型的对象作为输入参数。这意味着你必须将对象转换成你想要工作的类型并确保你的集合中仅仅包含那种类型的对象。如果这个不是确定的,你能使用instanceof测试指定的对象是否为那种类型。(译者注:根据需要,可以使用范型解决类型转换问题,由于这篇文章实在是太早了,所以作者才有了这段内容。)

         有时候,你可能不喜欢为每一个FilterCriteria定义一个单独的类,这种情况下可以使用匿名的内部类。
    为了使解决方法简单些,我对这个过滤器并没有使用OR功能。换句话说,每次你增加一个FilterCriteria到你的CollectionFilter,可以当作是SQL中的AND操作。然而,你也能容易的在一个FilterCriteria增加像OR的功能。例如:




      
    class
      EitherOrColorFilterCriteria
    implements
      FilterCriteria{
         
    private
      String color1;
         
    private
      String color2;
         
    public
      
    boolean
      passes(Object o){
             
    return
      ((Car)o).getColor().equals(color1)
    ||
      ((Car)o).getColor().equals(color2);
         }
    }

    结论     如你所看到的,基于多个条件来过滤集合是简单的。每一个FilterCriteria对象仅对它表示的单个的过滤逻辑负责。CollectionFilter然后联合所有的过滤器来产生想要的结果。对于其它种类的集合处理的相似的解决方法也是可以想到的(除了删除操作)。这个解决方法使用了职责链和迭代器模式:CollectionFilter在集合之上迭代,对于集合中的每一个对象,FilterCriteria对象被当作职责链,而每一个过滤器能决定其它的过滤器是否是需要的。

    作者Bio David Rappoport 已经在IBM Global Services 和 Credit Suisse Application Development 工作了五年, 在那儿他开发J2EE领域的软件。他是一个SUN认证的Java 2 程序员,SUN认证的Java 2开发者,SUN认证的J2EE 架构师,和SUN认证的业务组件开发者。他和他的妻子几两个孩子生活在瑞士。

    注:该文为本人第一篇和技术相关的翻译文章(论文就不算了)。由于本人水平有限,翻译中难免有不对的地方,欢迎各位朋友指正。该文出处为http://www.javaworld.com/javaworld/jw-10-2004/jw-1018-filter.HTML,是一篇很早的文章(2004年),内容上也算是比较简单的。



      
      
       
       
         
       
                         
         
       
      
    复制代码

    源码下载:http://www.java3z.com/cwbwebhome/dir1/dir5/test54.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 22:04 , Processed in 0.374155 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表