比较ArrayList中的列表

时间:2018-03-21 13:42:39

标签: java string list collections

我有一个包含以下字符串的文本文件(软件的版本):

1_10_2_0_154
3_10_5_2_10
2_10_4_1
3_10_5_1_37

我试图找到最新版本,在这种情况下, 3_10_5_2_10 是我尝试使用java显示的版本。

目前,这是我的代码:

    BufferedReader br;
    String version;
    ArrayList<List<Integer>> array = new ArrayList<List<Integer>>();
    List<Integer> liste = new ArrayList<Integer>();

    try{
        br = new BufferedReader(new FileReader(new File(FILEPATH)));

        while((version= br.readLine()) != null)
        {
            liste = Arrays.asList(version.split("_")).stream().

    map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());

            array.add(liste);
        }

        for(int i = 0; i < array.size(); i++)
        {   
            for (List l: array)
            {
                Object z = l.get(i);
                List<Object> listes = new ArrayList<Object>();
                listes.add(z);
                System.out.println(listes);
            }               
        }
        br.close();

        System.out.println(array);
    }catch(FileNotFoundException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }      

我做了一个循环来将字符串保存到ArrayList&gt;像:

[[1,10,2,0,154] , [3,10,5,2,10], [2,10,4,1], [3,10,5,1,37]]

我想获取每个列表的元素并进行比较以找到最大的一个(最近的一个),但我不知道这样做..

7 个答案:

答案 0 :(得分:4)

我建议您使用对象方法,使用 compareTo 方法定义名为版本的类,然后在集合<上使用方法排序 / strong>类您可以简单地对您的版本进行排序。

<强>优点

  • 清除并清除代码
  • 数据验证

主要

public class Main {

    public static void main(String[] args){

        List<Version> versions = Arrays.asList(
                Version.create("1_10_2_0_154"),
                Version.create("3_10_5_2_10"),
                Version.create("2_10_4_1_49"),
                Version.create("3_10_5_1_37"));

        versions.sort(Version::compareTo);

        System.out.println(versions.get(0).toString());
    }

}

版本:

public class Version implements Comparable<Version> {

    private final int major;
    private final int minor;
    private final int bug;
    private final int release;
    private final int build;

    public Version(int major, int minor, int bug, int release, int build) {
        this.major = major;
        this.minor = minor;
        this.bug = bug;
        this.release = release;
        this.build = build;
    }

    public int getMajor() {
        return major;
    }

    public int getMinor() {
        return minor;
    }

    public int getBug() {
        return bug;
    }

    public int getRelease() {
        return release;
    }

    public int getBuild() {
        return build;
    }

    @Override
    public String toString() {
        return "Version{" +
                "major=" + major +
                ", minor=" + minor +
                ", bug=" + bug +
                ", release=" + release +
                ", build=" + build +
                '}';
    }



    public static Version create(String value){

        String[] splitRes = value.split("_");
        List<Integer> intValues = new ArrayList<>();

        for(String v : splitRes){
            intValues.add(Integer.parseInt(v));
        }

        return create(intValues);
    }

    public static Version create(List<Integer> values){

        if(Objects.requireNonNull(values).size() < 5)
            throw new IllegalArgumentException();

        return new Version(
                values.get(0),
                values.get(1),
                values.get(2),
                values.get(3),
                values.get(4)
        );
    }


    @Override
    public int compareTo(Version that) {
        if (this.major > that.major) {
            return -1;
        } else if (this.major < that.major) {
            return 1;
        }

        if (this.minor > that.minor) {
            return -1;
        } else if (this.minor < that.minor) {
            return 1;
        }

        if (this.bug > that.bug) {
            return -1;
        } else if (this.bug < that.bug) {
            return 1;
        }

        if (this.release > that.release) {
            return -1;
        } else if (this.release < that.release) {
            return 1;
        }

        if (this.build > that.build) {
            return -1;
        } else if (this.build < that.build) {
            return 1;
        }
        return 0;
    }
}

更新1

正如@Henrik所建议的那样,我使用Java 8方法更新了列表排序。

更新2

我颠倒了 compareTo 方法,所以现在你可以简单地在列表上调用 sort 方法并传递方法参考 Version :: compareTo

更新3

版本类的更具动态性的解决方案:

public class Version implements Comparable<Version> {

    private final List<Integer> values;

    public Version(List<Integer> values) {
        this.values = values;
    }

    public List<Integer> getValues() {
        return values;
    }

    @Override
    public String toString() {

        return String.join("_", values
                .stream()
                .map(Object::toString)
                .collect(Collectors.toList()));
    }

    @Override
    public int compareTo(Version that) {

        List<Integer> thatValues = that.getValues();

        for(int index = 0; index < values.size(); index++){

            Integer value = values.get(index);
            Integer thatValue = thatValues.get(index);

            if (value > thatValue) {
                return -1;
            } else if (value < thatValue) {
                return 1;
            }
        }

        return 0;
    }


    public static Version create(String value){

        String[] splitRes = value.split("_");
        List<Integer> intValues = new ArrayList<>();

        for(String v : splitRes){
            intValues.add(Integer.parseInt(v));
        }

        return new Version(intValues);
    }
}

答案 1 :(得分:1)

您可以撰写Comparator来比较两个列表

Comparator<List<Integer>> comparator = (list1, list2) -> {
    Iterator<Integer> iteratorA = list1.iterator();
    Iterator<Integer> iteratorB = list2.iterator();

    //It iterates through each list looking for an int that is not equal to determine which one precedes the other
    while (iteratorA.hasNext() && iteratorB.hasNext()) {
        int elementA = iteratorA.next();
        int elementB = iteratorB.next();

        if (elementA > elementB) {
            return 1;
        } else if (elementA < elementB) {
            return -1;
        }
    }
    //All elements seen so far are equal. Use the list size to decide
    return iteratorA.hasNext() ? 1 : iteratorB.hasNext() ? -1 : 0;
};

您可以将其排序为

Collections.sort(list, comparator);

编辑:您可以参考David Geirola's answer将版本字符串转换为POJO并将比较器逻辑移到其中。但这与输入字符串格式高度绑定/耦合。我的解决方案适用于任何List<List<Integer>>

答案 2 :(得分:0)

一个简单的面向对象的方法是创建表示版本号的对象,让我们称之为VersionNumber,它将具有解析字符串的工厂方法的构造函数。此VersionNumber类应实现Comparable接口并实现方法compareTo。

以下是使用Comparable Why should a Java class implement comparable?

的提示

然后你可以轻松编写一个算法来找到最大版本,或者谷歌一些可以为你做这件事的库。

答案 3 :(得分:0)

将数组一起打成一个数字,然后进行数字比较。

class Scratch
{
    public static void main(String[] args)
    {
        List<List<Integer>> arr = new ArrayList<>();
        arr.add(fromArray(new Integer[]{1,10,2,0,154}));
        arr.add(fromArray(new Integer[]{3,10,5,2,10}));
        arr.add(fromArray(new Integer[]{2,10,4,1,49}));
        arr.add(fromArray(new Integer[]{3,10,5,1,37}));

        Integer[] maxLengths = {0,0,0,0,0};
        for (List<Integer> v : arr)
        {
            for(int idx = 0; idx < v.size(); idx++)
            {
                Integer n = v.get(idx);
                int curMaxLen = maxLengths[idx];
                maxLengths[idx] = Math.max(n.toString().length(), curMaxLen);
            }
        }
        Long largest = arr.stream().map(v -> {
            StringBuilder result = new StringBuilder();
            for(int idx = 0; idx < v.size(); idx++)
            {
                Integer n = v.get(idx);
                int maxLen = maxLengths[idx];
                result.append(String.format("%-" + maxLen + 's', n).replace(' ', '0'));
            }
            return result.toString();
        }).map(Long::valueOf).max(Comparator.naturalOrder()).get();
        System.out.println(largest);
    }

    public static List<Integer> fromArray(Integer[] array)
    {
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, array);
        return list;
    }
}

答案 4 :(得分:0)

它没有优化但应该有效。您可以使用两个比较器。

static List<String> versions = Arrays.asList(
        "1_10_2_0_154",
        "3_10_5_2_10",
        "2_10_4_1_49",
        "3_10_5_1_37");

static Comparator<List<Integer>> c = (o1,o2) -> {
    int length = o1.size()>o2.size()?o2.size():o1.size();
    for (int i = 0; i < length; i++) {
        int i1 = o1.get(i);
        int i2 = o2.get(i);
        if (i1 != i2)
            return i1 - i2;
    }
    return 0;
};
static Comparator<List<Integer>> c2 = (o1,o2) -> {
    Iterator<Integer> i1=o1.iterator();
    Iterator<Integer> i2=o2.iterator();
    while (i1.hasNext() && i2.hasNext()){
        int i = i1.next()-i2.next();
        if (i!=0) return i;
    }
    return 0;
};

static Optional<List<Integer>> getTheMostRecentVersion(List<String> versions) {
    return versions.stream().
            map(s -> Arrays.stream(s.split("_")).
                    map(Integer::parseInt).
                    collect(Collectors.toList())).max(c2);
}

答案 5 :(得分:0)

我认为这个文本文件可能非常大,最好比较每一行(而不是将所有行存储到集合中以便对其进行排序):

modelBuilder.Conventions.Add(new PrefixConvention());

答案 6 :(得分:0)

将军ListComparator应该会有所帮助。

static class ListComparator<T extends Comparable<T>> implements Comparator<List<T>> {

    @Override
    public int compare(List<T> o1, List<T> o2) {
        for (int i = 0; i < Math.max(o1.size(), o2.size()); i++) {
            int diff =
                    // Off the end of both - same.
                    i >= o1.size() && i >= o2.size() ? 0
                    // Off the end of 1 - the other is greater.
                    : i >= o1.size() ? -1
                    : i >= o2.size() ? 1
                    // Normal diff.
                    : o1.get(i).compareTo(o2.get(i));
            if (diff != 0) {
                return diff;
            }
        }
        return 0;
    }
}

private static final Comparator<List<Integer>> BY_VERSION = new ListComparator<Integer>().reversed();

public void test(String[] args) {
    String[] tests = {
            "1_10_2_0_154",
            "3_10_5_2_10",
            "2_10_4_1_49",
            "3_10_5_1_37",
            "3_10_5_1_37_0"
    };
    System.out.println("Before: " + Arrays.toString(tests));
    System.out.println("After:  " + Arrays.stream(tests)
            // Split into parts.
            .map(s -> s.split("_"))
            // Map String[] to List<Integer>
            .map(a -> Arrays.stream(a).map(s -> Integer.valueOf(s)).collect(Collectors.toList()))
            // Sort it.
            .sorted(BY_VERSION)
            // Back to a new list.
            .collect(Collectors.toList()));
}