迭代列表并根据日期进行分组

时间:2015-04-14 15:07:33

标签: java

我正在努力实现,我正在寻找基于日期对列表进行分组的方法。我失去了属性如下:

List<Attribute> attributes

,其中     Attribute.java如下所示

public class Attribute
{
    Integer getValue();
    List<String> getString();
    Date getDate();
}

我正在寻找一种方法,在遍历Attribute列表的同时,我可以创建一个元素列表(当前日期)和基于具有相同IntegerValue的日期(过去)的元素映射。 / p>

我的代码如下:

List<Attribute> currentElement = new ArrayList<Attribute>();
Map<Integer, List<Attribute>> historicalElement = new HashMap<Integer, List<Attribute>>();

//iterating the entire list
for(final Attribute attribute : attributes) 
{
  if(attribute.getDate() == currentDate)
  {
      currentElement.add(attribute);
  }
  if(attribute.getDate() < currentDate)
  {
      historicalElement.put(attribute.getValue(), attribute)     
  }
}

声明

historicalElement.put(attribute.getValue(), attribute)     

不会工作,因为

The method put(Integer, List<Attribute>) in the type Map<Integer,List<Attribute>> is not applicable for the arguments (Integer,   Attribute).

我们有什么方法可以实现该地图,而不是输入Cast到List。

谢谢!!!

4 个答案:

答案 0 :(得分:2)

投射到列表根本没有帮助。你只会获得ClassCastException。最简单的方法可能就是:

if(attribute.getDate() < currentDate)
{
    List<Attribute> list = historicalElement.get(attribute.getValue());
    if(list == null){
        list = new ArrayList<>();
        historicalElement.put(attribute.getValue() , list);
    }

    list.add(attribute);  
}

答案 1 :(得分:1)

编辑:保罗的答案在这里更好。

看起来像guava multimap的工作,你可以这样做:

Map<Integer, List<Attribute>> historicalElement = Multimaps.newListMultimap();
for(final Attribute attribute : attributes) {
    historicalElement.put(attribute.getValue(), attribute)
}

应该这样做。

那么,除了你想按日期分组外?这有点棘手。

答案 2 :(得分:1)

首先,您需要修复日期比较。您不使用==运算符比较日期。

现在,在地图中添加新条目时,您首先要检查现有密钥。如果没有,则创建一个具有新值的新ArrayList

if(attribute.getDate().compareTo(currentDate) < 0) {
    if (historicalElement.containsKey(attribute.getValue())) {
        historicalElement.get(attribute.getValue()).add(attribute);
    } else {
        historicalElement.put(attribute.getValue(), 
             new ArrayList<Attribute>(Arrays.asList(attribute)));     
    }
}

如果您使用的是Java 8,则可以直接使用Map#merge()方法来避免额外的测试:

if(attribute.getDate().compareTo(currentDate) < 0) {
    historicalElement.merge(
                attribute.getValue(), 
                new ArrayList<Attribute>(Arrays.asList(attribute)), 
                ArrayList::addAll);
}

您也可以在此处使用Stream API和lambda:

List<Attribute> currentElement = attributes.stream()
      .filter(a -> a.getDate().compareTo(currentDate) == 0)
      .collect(Collectors.toList());
Map<Integer, List<Attribute>> historicalElement = attributes.stream()
      .filter(a -> a.getDate().compareTo(currentDate) < 0)
      .collect(Collectors.groupingBy(Attribute::getValue));

答案 3 :(得分:-1)

您是不是想在Attribute中将 Map放在需要List属性的地方:

//iterating the entire list
for(final Attribute attribute : attributes) 
{
  if(attribute.getDate() == currentDate)
  {
      currentElement.add(attribute);
  }
  if(attribute.getDate() < currentDate)
  {
      historicalElement.put(attribute.getValue(), attribute)  // HERE   
  }
}

如果您希望它是单一属性,则应更改:

来自: Map<Integer, List<Attribute>> historicalElement = new HashMap<Integer, List<Attribute>>();

收件人: Map<Integer, List<Attribute>> historicalElement = new HashMap<Integer, Attribute>();