简体   繁体   English

如何合并清单 <Date> list1和List <Date> Java中的list2?

[英]How to Union List<Date> list1 and List<Date> list2 in Java?

  public class ArrayOfArrayList {
public static void main(String[] args) {
    List<Date> dateList1 = new ArrayList<Date>();
    List<Date> dateList2 = new ArrayList<Date>();
    Calendar cal = new GregorianCalendar();
    for(int i = 0; i < 5; i++) {
        Date d1 = new Date();
        cal.setTime(d1);
        cal.add(Calendar.DATE, i);
        dateList1.add(cal.getTime());
    }
    System.out.println("   *************** Date List 1st ****************");
    for(Date date1 : dateList1) {
        System.out.println("1stList"+date1);
    }
    System.out.println("   *************** Date List 1st ****************");

    for(int i = 2; i < 8; i++) {
        Date d2 = new Date();
        cal.setTime(d2);
        cal.add(Calendar.DATE, i);
        dateList2.add(cal.getTime());
    }
    System.out.println("   *************** Date List 2nd ****************");
    for(Date date2 : dateList2) {
        System.out.println("2ndList"+date2);
    }
    System.out.println("   *************** Date List 2nd ****************");

    System.out.println("   *********** Start Union Dates ************");
    List<Date> finalList = union(dateList1,dateList2);
    Collections.sort(finalList);
    System.out.println("\n   ********* After Union Dates ***********");
    for(Date fDate : finalList) {
        System.out.println(fDate);
    }
    System.out.println("\n ********* After Union Dates **********");    
}

private static  List<Date> union(List<Date> dateList1, List<Date> dateList2)       {
    HashSet<Date> dateSet = new HashSet<Date>();
    dateSet.addAll(dateList1);
    dateSet.addAll(dateList2);
    List<Date> finalDateList = new ArrayList<Date>(dateSet);
    return finalDateList;
}}

with Union Method still i am getting Duplicate Dates could you anyone help me to fix this issue some time answer comes correct but sometime duplicate still present please guide me 与联盟方法仍然我得到重复的日期,有人可以帮我解决这个问题,有时答案是正确的,但有时重复仍然存在,请指导我

O/P O / P

     *************** Date List 1st ****************
    1stListFri Oct 21 00:38:53 IST 2016
    1stListSat Oct 22 00:38:53 IST 2016
    1stListSun Oct 23 00:38:53 IST 2016
    1stListMon Oct 24 00:38:53 IST 2016
    1stListTue Oct 25 00:38:53 IST 2016
    *************** Date List 1st ****************
    *************** Date List 2nd ****************
    2ndListSun Oct 23 00:38:53 IST 2016
    2ndListMon Oct 24 00:38:53 IST 2016
    2ndListTue Oct 25 00:38:53 IST 2016
    2ndListWed Oct 26 00:38:53 IST 2016
    2ndListThu Oct 27 00:38:53 IST 2016
    2ndListFri Oct 28 00:38:53 IST 2016
    *************** Date List 2nd ****************
    *************** Start Union Dates ****************

    *************** After Union Dates ****************
         Fri Oct 21 00:38:53 IST 2016
         Sat Oct 22 00:38:53 IST 2016
         Sun Oct 23 00:38:53 IST 2016
         Sun Oct 23 00:38:53 IST 2016
         Mon Oct 24 00:38:53 IST 2016
         Mon Oct 24 00:38:53 IST 2016
         Tue Oct 25 00:38:53 IST 2016
         Tue Oct 25 00:38:53 IST 2016
         Wed Oct 26 00:38:53 IST 2016
         Thu Oct 27 00:38:53 IST 2016
         Fri Oct 28 00:38:53 IST 2016

   *************** After Union Dates ****************

As you can see the Above Outputs still duplicate is present in the final list after Union of two dates 如您所见,在两个日期合并之后的最终列表中,上述输出仍然重复

Your problem is here; 您的问题在这里; as you do: 像你一样做:

dateList1.add(cal.getTime());

You assume that two dates are equal when their printout (like above) is equal. 您假设两个日期相等(当它们的打印输出相同时)。 But that is not true! 但这不是真的! You simply forgot that "dates" include milli seconds , too. 您只是忘记了“日期”也包含毫秒 If you change your formatting to include that information, you will find that your dates might have same hours:minutes:seconds ... but all different milli second values! 如果您更改格式以包括该信息,则会发现日期可能具有相同的小时:分钟:秒...,但所有毫秒值都不相同

Thus the Set does not see duplicated entries; 因此,设置不会看到重复的条目; it just sees all different objects! 它只是看到所有不同的物体!

So, in order to make your union work, you have to "normalize" those parts within a Date that you want to ignore. 因此,为了使联合工作正常,您必须在要忽略的日期内“标准化”那些部分。 Two ways there: 有两种方式:

  1. As mentioned in the comments, just push "0" for milliseconds into all the created Date objects! 如注释中所述,只需将“ 0”推入所有创建的Date对象中就可以了!
  2. You could be using a TreeSet and a custom Comparator; 您可能正在使用TreeSet和自定义的 Comparator。 and that Comparator can ensue that Dates that are only different on milliseconds are showing up as equal. 并且比较器可以确保仅以毫秒为单位的不同日期显示为相等。 But that isn't really a great approach, as you have no control which of your Dates will "survive" then. 但这并不是一个好方法,因为您无法控制哪个日期可以“生存”。

tl;dr TL;博士

SortedSet<ZonedDateTime> union = 
    new TreeSet<>().addAll( zdtsA ).addAll( zdtsB ) ;

Details 细节

The accepted Answer by GhostCat is correct. GhostCat接受的答案是正确的。 The poorly designed toString method masked the fractional second that made each seemingly-duplicate value actually distinct. 设计欠佳的toString方法掩盖了小数秒,这使得每个看似重复的值实际上都与众不同。

Avoid legacy date-time classes 避免使用旧的日期时间类

The old date-time classes such as java.util.Date and java.util.Calendar are poorly designed, confusing, and troublesome. 旧的日期时间类(例如java.util.Datejava.util.Calendar设计不良,令人困惑且麻烦。 They are now legacy , supplanted by the java.time classes. 它们现在是遗留的 ,由java.time类取代。

Among the many reasons to replace those old classes is the poor choice of behavior of the toString method. 替换那些旧类的众多原因之一是toString方法的行为选择toString Not only does it dynamically apply a time zone to a value that is actually in UTC, it also masks the fractional second. 它不仅动态地将时区应用于UTC实际值,而且还掩盖了小数秒。 That hiding of the fractional second is your core problem here as you did not realize the values were identical to the second but not identical in the fraction. 在这里,小数秒的隐藏是您的核心问题,因为您没有意识到值与小数秒相同但在小数中并不相同。

java.time java.time

The equivalent of java.util.Date is Instant . 等效于java.util.DateInstant The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction). Instant类以UTC表示时间轴上的时刻,分辨率为纳秒 (最多十进制的九(9)位数字)。

Fortunately, the implementation of the toString methods in the java.time classes such as Instant do not hide the fractional second. 幸运的是,java.time类(例如Instant toString方法的实现不会隐藏小数秒。 By default the fractional second, if any, is displayed in groups of 3 digits as needed for the value. 默认情况下,如果需要,小数秒(如果有的话)以3位数字的组显示。 So you will see zero, three, six, or nine digits of fractional second when generating a String to represent the date-time value. 因此,在生成表示日期时间值的字符串时,您将看到零,三,六或九个小数秒的数字。

Instant

To convert to/from java.time, look to new methods added on the old classes. 要与java.time进行相互转换,请查找在旧类上添加的新方法。

Instant instant = myUtilDate.toInstant();

Truncate 截短

You can truncate the fractional second if desired. 如果需要,您可以截断小数秒。 You can truncate to any granularity you want, as defined in a TemporalUnit such as those implemented in ChronoUnit such as whole seconds, minutes, hours, etc. 您可以将其截断为所需的任意粒度,如TemporalUnit定义的粒度(例如ChronoUnit实现的ChronoUnit例如整秒,分钟,小时等。

Instant instant = myUtilDate.toInstant().truncatedTo( ChronoUnit.SECONDS );

If you want to increment by 24-hour increments, call the plus method on Instant . 如果要以24小时为增量递增,请在Instant上调用plus方法。

Instant dayLater = instant.plus( 1 , ChronoUnit.DAYS );

ZonedDateTime

If you want to increment by days that respect anomalies such as Daylight Saving Time (DST) rather than simply adding 24-hour increments, apply a time zone ( ZoneId ) to get a ZonedDateTime object. 如果您想增加尊重异常的天数,例如夏令时(DST),而不是简单地添加24小时增量,请应用时区( ZoneId )以获取ZonedDateTime对象。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

By the way, if you only cared about date and not time-of-day, extract a LocalDate with a call to toLocalDate . 顺便说一句,如果您只关心日期而不是时间,请提取对LocalDate的调用toLocalDate

Increment by days, and collect. 逐日递增,并收集。

int count = 5 ;
List<ZonedDateTime> datesA = new ArraySet<>( count );
for( int i = 1 , i <= count , i++ ) {
    datesA.add( zdt );
    // Prepare for next loop.
    zdt = zdt.plusDays( 1 );
}

SortedSet

A TreeSet is a Set and so eliminates duplicates. TreeSet是一个Set ,因此可以消除重复项。 A TreeSet is also a SortedSet (see Tutorial ) and so keeps the values sorted, in this case sorted in chronological order. TreeSet也是SortedSet (请参见Tutorial ),因此将值保持排序,在这种情况下,将按时间顺序排序。 To union while eliminating duplicates, add all elements of both List objects to a SortedSet like TreeSet . 工会同时消除重复,两者的所有元素添加List对象添加到SortedSetTreeSet

SortedSet<ZonedDateTime> union = new TreeSet<>();
union.addAll( datesA );
union.addAll( datesB );

You can make a List from the SortedSet similar to code seen in the Question. 您可以从SortedSet创建一个List ,类似于在Question中看到的代码。 The SortedSet iterator traverses the set in ascending element order, so the resulting List will be in chronological order. SortedSet迭代器按元素升序遍历集合,因此生成的List将按时间顺序排列。

List<ZonedDateTime> finalDateList = new ArrayList<>(dateSet);

For more discussion of SortedSet , see this Question , this , and this . 有关SortedSet更多讨论,请参见thisthisthis


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , .Calendar , & java.text.SimpleDateFormat . 这些类取代了麻烦的旧式旧式日期时间类,例如java.util.Date.Calendarjava.text.SimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to java.time. 现在处于维护模式Joda-Time项目建议迁移到java.time。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 And search Stack Overflow for many examples and explanations. 并在Stack Overflow中搜索许多示例和说明。 Specification is JSR 310 . 规格为JSR 310

Where to obtain the java.time classes? 在哪里获取java.time类?

  • Java SE 8 and SE 9 and later Java SE 8SE 9及更高版本
    • Built-in. 内置。
    • Part of the standard Java API with a bundled implementation. 标准Java API的一部分,具有捆绑的实现。
    • Java 9 adds some minor features and fixes. Java 9添加了一些次要功能和修复。
  • Java SE 6 and SE 7 Java SE 6SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport . java.time的许多功能在ThreeTen- Backport中都被反向移植到Java 6和7。
  • Android Android的

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

Use set as filter, not as storage: 将集合用作过滤器,而不用作存储:

    HashSet<String> dateSet = new HashSet<String>();
    return Stream.concat(dateList1.stream(), dateList2.stream())
            .filter(d -> dateSet.add(d.toString()))
            .collect(Collectors.toList());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM