无法删除列表中的重复项

时间:2017-06-13 08:53:31

标签: java algorithm list duplicates

我最近一直在处理有日期(实际上是字符串)和ID的对象列表。日期以这种方式存储,带有一个字符串:“yyyy-mm-dd”。 所以我有一个非常长的列表(大约80 000个元素)看起来像这样:

[{id:"15655454", date:"2014-11-15"}, {id:"15655454", date:"2014-11-15"}, {id:"15655454", date:"2014-11-15"}, {id:"15655454", date:"2014-10-17"}, {id:"15655454", date:"2014-10-17"}, {id:"15655454", date:"2014-10-17"}, {id:"15655454", date:"2014-10-17"}, {id:"15655454", date:"2014-10-17"}, {id:"15655455", date:"2014-09-23"}, ...]

它实际上是一个java类,有点复杂,但全球的想法就在这里。 (它确实不仅仅有两个字段,但我认为这并不重要)

如您所见,它按ID排序。

我想做的是: - 如果一个ID有多个日期:只保留最新日期。 - 如果一个ID有几个相同的最新日期:保留所有日期。

所以这就是我到目前为止所尝试的内容:

List<Element> results = new ArrayList<Element>();
results.initiateList();

int count = 0;

while(count < results.size()-1) {
    if (results.get(count).getID().equals(results.get(count+1).getID())) {
            String[] dateI = results.get(count).getDate().split("-");
            String[] dateJ = results.get(count+1).getDate().split("-");
            int yearI = Integer.parseInt(dateI[0]);
            int yearJ = Integer.parseInt(dateJ[0]);
            int monthI = Integer.parseInt(dateI[1]);
            int monthJ = Integer.parseInt(dateJ[1]);
            int dayI = Integer.parseInt(dateI[2]);
            int dayJ = Integer.parseInt(dateJ[2]);

            if (results.get(count).getDate()== null) {
                results.remove(count);
                if (count != 0) {
                    count--;
                }
            } else if (results.get(count+1).getDate()== null) {
                results.remove(count+1);
            } else if ( yearI > yearJ ) {
                results.remove(count+1);
            } else if ( yearI < yearJ ) {
                results.remove(count);
                if (count != 0) {
                    count--;
                }
            } else if ( yearI == yearJ && monthI > monthJ ) {
                results.remove(count+1);
            } else if ( yearI == yearJ && monthI < monthJ ) {
                results.remove(count);
                if (count != 0) {
                    count--;
                }
            } else if ( yearI == yearJ && monthI == monthJ && dayI > dayJ ) {
                results.remove(count+1);
            } else if ( yearI == yearJ && monthI == monthJ && monthI < monthJ ) {
                results.remove(count);
                if (count != 0) {
                    count--;
                }
            } else if ( yearI == yearJ && monthI == monthJ && dayI == dayJ ) {
                count++;
            }
        } else {
            count++;
        }


    }

但这不起作用,我不明白为什么。我觉得我已经考虑了所有可能的情况,但仍然没有删除所有重复的情况。问题是我仍然有一些重复,例如,列表仍然包含一个ID的几个不同日期。

方法initiateList(),getDate()和getID()已正确实现,因为我在很多其他不同的地方使用它们,并且它们在那里工作正常。 InitiateList()将所有元素放在列表中,如果我尝试在控制台上显示它们就可以正常工作。

我没有看到while循环有什么问题,但我想我错过了一些东西(而且它可能非常基本......)

2 个答案:

答案 0 :(得分:2)

我认为尝试与邻居元素进行比较是错误的,因为没有必要这两个具有相同id的情况。也许你应该通过在收藏家中使用groupBy来尝试不同的方法

 public List<Element> removeDuplicates(List<Element> theList) {
    // Getting a map where key is an id of element and the list is all the elements with the same id
    Map<String, List<Element>> theData = theList.stream().collect(Collectors.groupingBy(elem -> elem.getId()));

    List<Element> result = new ArrayList<>();
    //Now we go over the map and from each list we take the element with newes date
    theData.forEach((id, elementsList) -> {
        Element elementWithNewstDate = getNewest(elementsList);
        result.add(elementWithNewstDate);
    });

    return result;
}

private Element getNewest(List<Element> elementsList) {
    // Sorting by newest date
    elementsList.sort(Comparator.comparing(element -> getDateFromElement(element)));
    //Taking the first one becouse it supose to be the newst if i am wrong take the last element
    return elementsList.get(0);
}

private Date getDateFromElement(Element element) {
    Date result = null;
    try {
        result = new SimpleDateFormat("yyyy-MM-dd").parse(element.getDate());
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return result;
}

请注意,它不是100%正确,但它应该有帮助作为一个例子

答案 1 :(得分:1)

您正在进行不必要的比较。您可以使用以下代码段将字符串转换为日期。

    String sDate1="2014-11-15";  
    Date date1=new SimpleDateFormat("yyyy-MM-dd").parse(sDate1);
    System.out.println("Date : "+date1);
    System.out.println("Date value :"+date1.getTime());

您可以比较相应日期getTime()的输出来决定更高/更低的日期。您可以减少代码并进行调试。