【问题标题】:How to find a maximum value of an index in a list of lists如何在列表列表中找到索引的最大值
【发布时间】:2019-09-03 16:09:56
【问题描述】:

我有一个对象列表列表,每个内部列表有 3 个对象元素,理论上是一个字符串和两个双精度对象,比如 ab,按顺序.

ArrayList<ArrayList<Object>> timings = new ArrayList<ArrayList<String>>()
        for (int runnerno = 0; runnerno < runners; runnerno++) {
            ArrayList<Object> thisrunner = new ArrayList<Object>();
            thisrunner.add(sc.next()); //string
            thisrunner.add(sc.nextDouble()); //double a 
            thisrunner.add(sc.nextDouble()); //double b
            timings.add(thisrunner);
            sc.nextLine();
        }

如何找出列表列表中的最大 a 值? IE。我想找到一个索引最大值。

【问题讨论】:

  • 欢迎来到 SO!获得答案的最佳方式是展示您到目前为止所做的工作并解释您遇到的问题。
  • 列表不是存储字符串和两个双精度的好方法。定义一个类来保存值。
  • 与其将Stringdouble 存储在List&lt;Object&gt; 中,不如创建一个自定义的Runner 类来存储数据,然后创建一个简单的List&lt;Runner&gt;
  • 最好的方法是使用堆数据结构,google how。

标签: java arrays list arraylist


【解决方案1】:

1) 让我们更好地封装您的数据对象,称之为 FooBar

public class FooBar {
    private String text;
    private Double x;
    private Double y;

    public FooBar() {

    }

    public FooBar(String text,Double x,Double y) {
        this.text = text;
        this.x = x;
        this.y = y;
    }

    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    public Double getX() {
        return x;
    }
    public void setX(Double x) {
        this.x = x;
    }
    public Double getY() {
        return y;
    }
    public void setY(Double y) {
        this.y = y;
    }
}

2) 填充 FooBars 列表

    List<FooBar> points = new ArrayList<FooBar>();

    for( int i = 0; i < 1000; i++ ) {
        FooBar f = new FooBar("Text" + i,
        ThreadLocalRandom.current().nextDouble(0, 100),
        ThreadLocalRandom.current().nextDouble(0, 100));
        points.add(f);
    }

3) 使用streams.max(带比较器)

    Optional<FooBar> maxFooBar = points.stream().max(new Comparator<FooBar>() {

        @Override
        public int compare(FooBar o1, FooBar o2) {
            return o1.getX().compareTo(o2.getX());
        }
    });

    System.out.println("Max Point: " + maxFooBar.get().getX());

4) 或者使用 Collections.max

    FooBar maxFooBar = Collections.max(points, new Comparator<FooBar>() {

        @Override
        public int compare(FooBar o1, FooBar o2) {
            return o1.getX().compareTo(o2.getX());
        }
    });
    System.out.println("Max Point: " + maxFooBar.getX());

5) 或者只是自己对列表进行排序并获取第一项(如果降序排序;如果升序排序,则获取最后一个)

    points.sort(new Comparator<FooBar>() {

        @Override
        public int compare(FooBar o1, FooBar o2) {
            return -1 * o1.getX().compareTo(o2.getX());
        }
    });
    System.out.println("Max Point: " + points.get(0).getX());

【讨论】:

  • 应该是double,而不是Double
  • #3 和#4 应该使用max(Comparator.comparingDouble(FooBar::getX))
【解决方案2】:

列表列表中Double类型的所有值的最大double值,像这样

public static double findMax(List<List> lists) {
    double max = Double.MIN_VALUE;
    for (List list : lists)
        for (Object o : list)
            if (o instanceof Double)
                if ((Double) o).doubleValue() > max)
                   max = ((Double) o).doubleValue();
    return max;
}

【讨论】:

    【解决方案3】:

    如果您使用 Comparator 接口按升序对每个单独的 Runner 对象进行排序,并且时序 treeSet 中的最后一个 Runner 对象将始终是最大值的索引

    我们不能使用 ArrayList,因为它没有任何支持 Comparator 作为参数的构造函数

    public class Runner {
         private String s;
         public double a;
         public double b;
    
         public Runner() {}
         public Runner(String s, double a, double b) {
             this.s = s;
             this.a = a;
             this.b = b;
         }
    
         @Override
         public String toString() {
             return s + " " + a + " " + b;
         }
    }
    

    调用类

     import java.util.Comparator;
     import java.util.Scanner;
     import java.util.TreeSet;
    
     public class Calling {
    
          public static void main(String[] args) {
               Scanner sc = new Scanner(System.in);
               int runners = 3;
               TreeSet<Runner> timings = new TreeSet<>(new MyComparator());
    
               for (int runnerno = 0; runnerno < runners; runnerno++) {
                    timings.add(new Runner(sc.nextLine(), Double.parseDouble(sc.nextLine()), Double.parseDouble(sc.nextLine())));               
               }
          System.out.println(timings);
          System.out.println("max value " + timings.last());
          }
    
     }
    
    class MyComparator implements Comparator<Runner> {
        @Override
        public int compare(Runner o1, Runner o2) {
            return Double.valueOf(o1.a).compareTo(Double.valueOf(o2.a));
       }
    }
    

    【讨论】:

    • Comparator 是泛型类,所以指定类型参数。不要使用原始泛型。这也消除了投射的需要。此外,Comparator 对找到最大 a 值有何用处?
    • 它将时序 TreeSet 排序在 a 和 b 的总和上以升序排列,所以最后一个元素将是最大值索引
    • 尽管如此,最后一个元素不一定是具有最大 a 值的元素,而这正是 OP 想要的。例如。您将按以下顺序排序:(2,3), (5,1), (3,4),因为这是总和的顺序 (5, 6, 7),但 a 的最大值为 5,并且位于中间元素中。
    猜你喜欢
    • 2012-03-05
    • 2012-07-16
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2015-10-24
    • 1970-01-01
    相关资源
    最近更新 更多