【问题标题】:Java 8 Sort using 2 fieldsJava 8 使用 2 个字段进行排序
【发布时间】:2017-08-02 10:28:08
【问题描述】:

基于某些条件,我已从 MongoDB 读取数据并创建了带有结果集的 List<Document>

List<Document> documentList = new ArrayList<Document>();

示例记录如下:

documentList: [
    Document{
        { _id=5975ff00a213745b5e1a8ed9,
            u_id=,
            visblty = 1,
            c_id=5975ff00a213745b5e1a8ed8,                
            batchid=null,
            pdate=Tue Jul 11 17:52:25 IST 2017, 
            locale=en_US,
            subject = "Document2"
        }     },
    Document{
        { _id=597608aba213742554f537a6,
            u_id=,
            visblty = 1,
            c_id=597608aba213742554f537a3, 
            batchid=null,
            pdate=Fri Jul 28 01:26:22 IST 2017,
            locale=en_US,
            subject = "Document2"
        }    } 
]

使用这个documentList,我再次使用一些条件进行过滤,然后我需要根据一些条件对过滤记录进行排序(我将收到请求)。

List<Document> outList = documentList.stream()
                .filter(d -> d.getInteger("visblty") == 1
                && (!StringUtils.isEmpty(req.pdate())? (d.getDate(CommonConstants.PDATE).after(afterDate)): true) 
                && (!StringUtils.isEmpty(req.pdate())? (d.getDate(CommonConstants.PDATE).before(beforeDate)): true)
                .sorted().skip(4).limit()
                .collect(Collectors.toList());

不确定如何排序(动态需要根据输入更改排序顺序,看起来像“pdate by DESC”或“subject by ASC"”)

点赞:"order by pdate DESC" or "order by pdate ASC"" or "order by subject DESC"

如何使用 Document 类的 Comparator 对象进行排序。

注意:我已经尝试了人们建议的几种方法,但我还没有得到任何运气。 提前谢谢!

【问题讨论】:

  • (!condition1? condition2: true)condition1 || condition2 的混淆变体。您可以通过在 &amp;&amp; 组合的两个术语中重复 condition1 来最大化它。整个过滤谓词可以简化为.filter( d -&gt; d.getInteger("visblty")==1 &amp;&amp; (StringUtils.isEmpty(req.pdate()) || d.getDate(CommonConstants.PDATE).after(afterDate)&amp;&amp;d.getDate(CommonConstants.PDATE) .before(beforeDate)) )。不过,StringUtils.isEmpty(req.pdate()) 不依赖于实际的流元素,因此,甚至可以在流操作之前进行评估,而不是针对每个元素。
  • 我看到你的过滤器 lambda 变得非常大。我建议您将其拆分并使用function composition 将这些部分添加在一起。
  • @MProkhorov:它又大又多余……我不知道它使用哪个日期类,但也许beforeafter 的组合可以被between 调用替换。然后,代码就像.filter(d -&gt; d.getInteger("visblty")==1) .filter(d -&gt; StringUtils.isEmpty(req.pdate()) || d.getDate(CommonConstants.PDATE).between(beforeDate, afterDate))
  • @Holger,是的,即使这样更好(在正确格式化 c 之后),根本不需要编写函数。

标签: java sorting java-8 java-stream


【解决方案1】:

您可以按如下方式使用组比较器和并行流:

List<Document> outList = documentList.stream()
                               .filter(....)
                               .sorted(Comparator.comparing(Document::getPdate)
                                                 .thenComparing(Document::getSubject))   
                               .parallel();  

【讨论】:

  • @KayV 上面的例子很容易理解。但我有一个澄清。如果我们想动态排序怎么办。
  • @Pearl 在这种情况下,您可以创建自定义比较器。并根据某些条件在排序 -> 比较 -> thenComparing 链中添加所需的比较器
【解决方案2】:

就 Java 代码而言,等效的排序比较器如下所示:

  1. order by pdate

    表示
    Comparator.comparing(Document::getPDate)
    
  2. order by subject

    表示
    Comparator.comparing(Document::getSubject)
    
  3. order by pdate, subject

    表示为:

    Comparator.comparing(Document::getPDate).thenComparing(Document::getSubject)

如果您在任何时候需要降序排列,您可以在比较器上调用reversed(),如下所示:

Comparator.comparing(Document::getPDate).reversed()
          .thenComparing(Comparator.comparing(Document::getSubject).reversed())

注意,thenComparing 方法被覆盖,提供了传入的能力:

  • a Comparator
  • a Function-extractor(如果提取的任何函数都是-a Comparable
  • a Function and a Comparator(因为当提取的值本身不是Comparable时,所以你不能使用它的自然顺序并且必须指定它应该如何比较。

【讨论】:

    【解决方案3】:

    尝试使用.sorted(Comparator comparator) 方法,而不是.sorted()

    您可以使用Comparator.comparing() 创建与.sorted(comparator) 一起使用的Comparator

    Comparator.comparing(Function keyExtractor)
        .reversed()
        .thenComparing(Function keyExtractor)
    

    例如:

    List<Document> outList = documentList.stream()
             // do your filtering here
            .sorted(Comparator.comparing(Document::getPdate).reversed()
                    .thenComparing(Document::getSubject))
            .skip(4)
            .limit()
            .collect(Collectors.toList());
    

    在此示例中,您可以使用方法引用 Document::getPdateDocument::getSubject 而不是像 d -&gt; d.getPdate()d -&gt; d.getSubject() 这样的 lambda 表达式

    【讨论】:

      猜你喜欢
      • 2018-01-28
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 2017-11-13
      • 2015-07-09
      • 1970-01-01
      • 2011-06-12
      相关资源
      最近更新 更多