我最近一直在处理具有日期(实际上是字符串)和 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 循环有什么问题,但我想我错过了一些东西(这可能是非常基本的......)
最佳答案
我认为尝试与相邻元素进行比较是错误的,因为它们不一定具有相同的 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% 正确,但作为示例应该有所帮助
关于java - 无法删除列表中的重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44516673/