10

我有对象的集合,Collection basics = periodic.getGeneratedBasic(); 当迭代这个集合并获取每个对象并转换它时,我可以提取每个对象的日期。现在在这一点上,我想在这个对象集合中检查哪一个是最小和最大的日期。

有谁知道这是怎么做到的吗?

Date max;
Date min;
for(Object o:basics){
      Basic b = (Basic) o;
      Date temp;
      if(b.State=='U'){
           basicAList.add(ba);
           dateCollection.add(b.firstDateTime);
           temp= ;
           if(b.firstDateTime <)
     }
  }
4

7 回答 7

19

在 Java 8 中,您可以执行以下操作:

final Date maxDate = dates.stream()
    .max(Date::compareTo)
    .get();
于 2015-09-18T06:08:47.780 回答
13

这是一个经典的最小和最大问题。无论您的对象是日期、字符串还是数字。重要的是它们具有可比性。

排序然后取最大值/最小值

最直接的方法就像其他人的答案一样,使用 java 内置的 Sort 方法对集合进行排序。然后将第一个和最后一个元素作为您的最小/最大对象。然而,它将线性时间O(n)问题变成了O(nlgn). 好吧,如果性能问题不是您正在考虑的问题。你可以跳过阅读我的休息文本。我会赞成@Quoi 的回答。

线性时间的简单方法:

保留两个变量最小值和最大值,然后查找集合中的每个元素。与您当前的最小值和最大值进行比较并获得正确的值。直到结束。

线性时间的优化方式

上面的方法很简单,但它带来了更多的比较(2n)。我们可以稍微优化一下。和上面一样,你有 min 和 max 两个变量。在循环中,您采用一对元素而不是单个元素。您首先比较该对中的两个元素。取较大的与您的最大变量进行比较,将较小的与您的最小变量进行比较。现在我们只需要进行3(n/2)比较。

希望能帮助到你

编辑

我认为代码并不难写。正如 Quoi 所建议的,如果代码可以使答案完整,我会添加它们。

请注意,在示例中,我使用了一个 int 数组。基本上它与 Date 对象相同。代码以单元测试方法编写。它看起来很长,因为我试图清楚地解释上面的想法。

@Test
    public void testx() {
        final int size = 300000;
        final int[] array = new int[size];
        final Random random = new Random();
        // fill a huge array for testing
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt();
        }

        int min1 = array[0], max1 = array[1], cmp1 = 0;
        int min2 = array[0], max2 = array[1], cmp2 = 0;

        for (int i = 2; i < array.length; i++) {
            min1 = array[i] < min1 ? array[i] : min1;
            cmp1++;
            max1 = array[i] > max1 ? array[i] : max1;
            cmp1++;
        }

        LOG.debug("linear time to find Max & Min simultaneously");
        LOG.debug("Size: {}", size);
        LOG.debug("Max : {}", max1);
        LOG.debug("Min : {}", min1);
        LOG.debug("Total comparisons : {}", cmp1);

        // optimized linear
        int bigger, smaller;
        final boolean odd = array.length % 2 == 1;
        final int till = odd ? array.length - 1 : array.length;
        for (int i = 2; i < till; i += 2) {

            if (array[i] >= array[i + 1]) {
                bigger = array[i];
                smaller = array[i + 1];
            } else {
                bigger = array[i + 1];
                smaller = array[i];
            }
            cmp2++;
            min2 = smaller < min2 ? smaller : min2;
            cmp2++;
            max2 = bigger > max2 ? bigger : max2;
            cmp2++;
        }
        if (odd) {
            min2 = array[size - 1] < min2 ? array[size - 1] : min2;
            max2 = array[size - 1] > max2 ? array[size - 1] : max2;
        }
        LOG.debug("====================================================");
        LOG.debug("optimized linear time to find Max & Min simultaneously");
        LOG.debug("Size: {}", size);
        LOG.debug("Max : {}", max2);
        LOG.debug("Min : {}", min2);
        LOG.debug("Total comparisons : {}", cmp2);
    }

输出

DEBUG:  linear time to find Max & Min simultaneously
DEBUG:  Size: 300000
DEBUG:  Max : 2147475519
DEBUG:  Min : -2147446732
DEBUG:  Total comparisons : 599996
DEBUG:  ====================================================
DEBUG:  optimized linear time to find Max & Min simultaneously
DEBUG:  Size: 300000
DEBUG:  Max : 2147475519
DEBUG:  Min : -2147446732
DEBUG:  Total comparisons : 449997
于 2012-10-18T09:48:29.060 回答
12

为什么不使用Collections.sort()然后取第一个/最后一个条目?您可以使用自然排序,也可以指定您自己的Comparator

请注意,这将对集合进行就地排序。它不会给你一个新的排序集合。

于 2012-10-18T09:33:38.193 回答
7

DateComparable,因此您可以使用 比较两个Dates compareTo()

dateOne.compareTo(dateTwo);

返回: 如果参数 Date 等于此 Date,则值为 0;如果此 Date 在 Date 参数之前,则值小于 0;如果此 Date 在 Date 参数之后,则值大于 0。

您还可以Collection使用Collections.sort()(O(n logn)) 对整体进行排序:

Collections.sort(dateCollection);

或者得到最大值Collections.max()和最小值Collections.min()(都在线性时间 O(n) 中)。

于 2012-10-18T09:32:34.953 回答
3
Date max = new Date(0);
Date min = new Date(0);
for(Object o:basics){
    Basic b = (Basic) o;
    if(b.State=='U'){
        basicAList.add(ba);
        dateCollection.add(b.firstDateTime);
        if(min.compareTo(b.firstDateTime) > 0) min = b.firstDateTime;
        else if(max.compareTo(b.firstDateTime) < 0) max = b.firstDateTime;
    }
}
于 2012-10-18T09:36:32.963 回答
1

您可以根据日期对您的收藏进行排序并获取它。如果按升序排列,您将首先获得最小日期,最后获得最大日期,如果按降序排序,则在顶部获得最大日期,最后获得最小日期。

于 2012-10-18T09:33:10.407 回答
1

你可以看看这个以前的 SO 帖子。您可以按日期对对象进行排序,然后选择集合中的第一个和最后一个项目。

于 2012-10-18T09:33:40.683 回答