How to Union List<date> list1 and List<date> list2 in Java?

时间:2016-10-20 19:20:34

标签: java arraylist duplicates union

  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

     *************** 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

3 个答案:

答案 0 :(得分:5)

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!
  2. You could be using a TreeSet and a custom 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.

答案 1 :(得分:2)

TL;博士

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

详细

accepted Answer by GhostCat是正确的。设计糟糕的toString方法掩盖了小数秒,使得每个看似重复的值实际上都是不同的。

避免遗留日期时间类

java.util.Datejava.util.Calendar等旧的日期时间类设计不当,令人困惑且麻烦。它们现在是legacy,取代了java.time类。

替换这些旧类的众多原因之一是toString方法的行为选择不当。它不仅动态地将时区应用于实际为UTC的值,还会屏蔽小数秒。隐藏小数秒是你的核心问题,因为你没有意识到值与第二个相同但在分数中不相同。

java.time

等同于java.util.Date的是InstantInstant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

幸运的是,java.time类中的toString方法的实现,例如Instant ,隐藏了小数秒。默认情况下,小数秒(如果有)将根据值的需要以3位数组显示。因此,当生成表示日期时间值的字符串时,您将看到零,三,六或九位小数秒。

Instant

要转换为/从java.time,请查看旧类上添加的新方法。

Instant instant = myUtilDate.toInstant();

截断

如果需要,您可以truncate小数秒。您可以截断为TemporalUnit中定义的任何粒度,例如ChronoUnit中实现的粒度,例如整秒,分钟,小时等。

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

如果您想以24小时为增量递增,请拨打Instant上的plus方法。

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

ZonedDateTime

如果您希望按照夏令时(DST)等异常增加天数而不是简单地添加24小时增量,请应用时区(ZoneId)来获取ZonedDateTime个对象

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

顺便说一句,如果您只关心日期而不关注时间,请拨打LocalDatetoLocalDate

按天增加,并收集。

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

TreeSetSet,因此可以消除重复项。 TreeSet也是SortedSet(请参阅Tutorial),因此保持值的排序,在这种情况下按时间顺序排序。要在删除重复项时进行联合,请将List个对象的所有元素添加到SortedSet TreeSet

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

您可以从问题中看到的代码List中创建SortedSet。 SortedSet迭代器以升序元素顺序遍历集合,因此生成的List将按时间顺序排列。

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

有关SortedSet的更多讨论,请参阅this Questionthisthis

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date.Calendar和&amp; java.text.SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 2 :(得分:-1)

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());