Java ArrayList添加具有相同ID的值

时间:2019-12-16 22:08:18

标签: java arraylist collections

所以我有一个数组列表,看起来像这样:<id,value,id,value,...>,我应该找到所有具有相同ID的元素,然后将尊重的值加到结果数组列表中(值始终在ID后面) 。起初,我认为问题很容易,因此继续尝试以下方法:

        List<String> resultList = new ArrayList<>();
        for(int i = 0; i < myList.size(); i+=2){

            BigInteger currentID = new BigInteger(myList.get(i));
            BigInteger currentSum = new BigInteger(myList.get(i+1));
            String currentId = myList.get(i);
            int j = 2;

            while(j < myList.size()){
                if(currentId.equals(myList.get(j))){
                 BigInteger value2 = new BigInteger(myList.get(j+1));
                 currentSum = currentID.add(value2);
                }
                resultList.add(currentId);
                resultList.add(String.valueOf(currentSum));
                j+=2;
            }
        }

不用说这是不正确的,许多问题之一是将尚未加在一起的值读入结果数组,因此我认为应该在循环中以某种方式删除它们。你们对如何解决这个有什么建议吗?

3 个答案:

答案 0 :(得分:3)

假设您可以使用地图: 我最初认为是使用Map<String, String> map = new HashMap();

Pseudo code:
For each (id,value pair) in resultList
   if map.get(id) exists
      add the value to the existing entry in the map
   else 
      add a new entry in the map for (id,value)

作为代码(注意:未经测试,可能无法编译,不会直接复制和粘贴):

Map<String, String> map = new HashMap<>();
for(int i = 0; i < myList.size(); i+=2){
   String listId = resultList.get(i); //get the Id from the resultList
   String listValue = resultList.get(i+1) //get the value from the resultList
   if(map.get(listId) != null) { // if the map has this Id
      map.put(listId, map.get(listId)+ listValue); // add the Id's list value
   }
   else { // if the map doesn't have this Id
      map.put(listId, listValue) // add the entry to the map
   }
}

然后,您可以获取结果map,并将变换返回到列表中。 我将让您编写代码以获取地图中的每个条目并将其添加到新列表中。 Google在这里可能会有所帮助。

答案 1 :(得分:2)

如果要使用流,则可以这样做。

给出如下列表:

      List<BigInteger> list = List.of(1,10,3,20,3,40,1,5,4,7,1,8,4,9,6,20)
           .stream().mapToLong(a -> a).mapToObj(
                  BigInteger::valueOf).collect(Collectors.toList());

首先将key作为ID在地图中累加和。

      Map<BigInteger, BigInteger> mapfinal =
            IntStream.iterate(0, i -> i < list.size(), i -> i += 2).mapToObj(
                  i -> new BigInteger[] { list.get(i), list.get(i + 1)
                  }).collect(Collectors.groupingBy(i -> i[0],
                        Collectors.reducing(BigInteger.ZERO,
                              a -> a[1],
                              (a, b) -> a.add(b))));

您可以在此停下来并仅使用地图,也可以将其转换为列表,就像您开始时使用id/value交替对一样。

       List<BigInteger> listfinal = mapfinal
            .entrySet()
            .stream()
            .flatMap(e -> Stream.of(e.getKey(), e.getValue()))
            .collect(Collectors.toList());

并打印列表。

      System.out.println(listfinal);
  

[1、23、3、60、4、16、6、20]

答案 2 :(得分:1)

最简单的方法是使用Map。但是,也可以在不更改输入数据结构或使用任何中间数据结构的情况下完成此操作。

这是未经测试的代码示例。我通过使用List<Integer>

简化了问题
    List<Integer> myList = ...
    List<Integer> resultList = new ArrayList<>();

    for (int i = 0; i < myList.size(); i += 2) {
        int id = myList.get(i);

        // Check that we haven't accumulated this id already
        boolean seen = false;
        for (int j = 0; j < i && !seen; j += 2) {
            seen = myList.get(j) == id;
        }
        if (seen) {
            continue;
        }

        // Accumulate values for 'id'
        int sum = myList.get(i + 1);
        for (int j = i + 2; j < myList.size(); j += 2) {
            if (myList.get(j) == id) {
                sum += myList.get(j + 1);
            }
        }
        // Send to output ...
        resultList.add(id);
        resultList.add(sum);
    }

此解决方案是O(N^2)。而且由于您实际上是在使用StringBigInteger而不是Integer,所以这甚至更昂贵。

使用Map的解决方案应为O(NlogN)O(N),具体取决于地图类型。

此外:在某些情况下,如果在第一个内部循环中使用resultList而不是myList,则速度会更快。但是我在上面的操作方式更加明显...

相关问题