在 ArrayList 中查找最小值、最大值、平均值

Finding min, max, avg in ArrayList

我无法区分每个不同的名称并计算它们的平均值、最小值和最大值。如果它只是针对一个列表执行此操作,我没有问题,但是当我必须仅使用某些名称的值时,它就会变得棘手。

public static ArrayList<Double> summarizeData (
    ArrayList<String> names, 
    ArrayList<Double> values,  
    ArrayList<String> categories, 
    int operation)
{
}

所以为了找到平均值,我会做类似的事情:

            //calculate sum of all array elements
            int sum = 0;

            for(int i=0; i < summarizeData.length ; i++)
                    sum = sum + summarizeData[i];

            //calculate average value
            double average = sum / summarizeData.length;

我的值列表如下:

Utah        5
Nevada      6
California  12
Oregon      8
Utah        9
California  10
Nevada      4
Nevada      4
Oregon      17
California  6

这些值来自 Junit 测试用例,所以我不能使用用方法声明的值,而是它们必须能够通过给定的任何测试用例。

使用 ArrayLists 的简单版本可能是这样的:

List<Integer> ints = new ArrayList<Integer>(); 

// Populate the list with some stuff
ints.add(5);
ints.add(20);

int sum = 0;

for (Integer anInt : ints) { // For each Integer in ints
    sum += anInt; // Add it's value to the sum
}

double average = sum / ints.size();

注意对 ArrayList 使用 java 的 for-each 或增强的 for 循环,这大大简化了迭代。另请注意,ArrayList 不能接受原始类型,因为它是泛型,因此我们必须利用自动装箱并使用装箱类型 Integer。最后,请注意 ArrayList 对象被声明为 List 但实例化为 ArrayList.

如果您的值是包含整数等的字符串。然后在你的循环中你必须将它们分开。正则表达式将是一个很好的工具。快速搜索后,这里接受的答案看起来很好解决number out of string in java

编辑:

这个答案太简单了,因为它不关心数据的上下文是什么。如果你想让每个州都有自己的一组统计数据。您可以将它们存储在 Map<String, Integer> 中,以将每个州的总和与该州的名称配对。

Map<String, Integer> stateSums = new HashMap<String, Integer>();

stateSums.put("Oregon", 17);
stateSums.put("Utah", 9); //etc

请记住,如果键已经存在,put 方法将覆盖现有值。所以如果你想给现有的 oregon 键添加一个新值,你会做这样的事情:stateSums.put("Oregon", stateSums.get("Oregon") + 8);

假设您想对它们进行排序,但要将它们的所有值完全分开!你也可以这样做:

Map<String, ArrayList<Integer>> stateValues = new HashMap<String, ArrayList<Integer>>

// Unless you can affirmatively determine whether or not this key
// already exists or not, you should check before each use to make sure
// you don't accidentally use a list that isn't created yet, or 
// over-write one with data with a new empty one
if (!stateValues.containsKey("Oregon")) {
    stateValues.put("Oregon", new ArrayList<>()); // It wasn't, create,
}
stateValues.get("Oregon").add(17);
stateValues.get("Oregon").add(8);

此解决方案仍需要您遍历原始数据。将州名和数字分开(可能是正则表达式),然后将每条数据放在适当的位置。

希望对您有所帮助!

P.S。如果您告诉我们您 运行 的 java 版本,我们可以优化结果以利用最新的可用功能。这将编译至少 6,也许 5,因此比它需要的更冗长,如果你是 运行 7 或 8.

使用 Java 8,这些类型的计算变得更加容易。假设您有以下包装器 class 来包装您的数据:

class Data {
    final String name;
    final int value;

    public Data(String name, int value) {
        this.name = name;
        this.value = value;
    }
}

您现在可以运行:

Stream.of(new Data("Utah"        ,5 ),
          new Data("Nevada"      ,6 ),
          new Data("California"  ,12),
          new Data("Oregon"      ,8 ),
          new Data("Utah"        ,9 ),
          new Data("California"  ,10),
          new Data("Nevada"      ,4 ),
          new Data("Nevada"      ,4 ),
          new Data("Oregon"      ,17),
          new Data("California"  ,6 ))
      .collect(Collectors.groupingBy(
          d -> d.name,
          Collectors.summarizingInt(d -> d.value)))
      .forEach((name, summary) -> System.out.println(name + ": " + summary));

产生:

Oregon: IntSummaryStatistics{count=2, sum=25, min=8, average=12.500000, max=17}
California: IntSummaryStatistics{count=3, sum=28, min=6, average=9.333333, max=12}
Utah: IntSummaryStatistics{count=2, sum=14, min=5, average=7.000000, max=9}
Nevada: IntSummaryStatistics{count=3, sum=14, min=4, average=4.666667, max=6}