具有List< String>的可比较类场地 [英] Comparable class with a List<String> field

查看:55
本文介绍了具有List< String>的可比较类场地的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的类,存储一个整数和一个字符串列表.

因为我想在 TreeSet<> 中使用此类,所以该类必须是 Comparable .但是,当尝试使用Java 8 Comparator 类时,我无法比较内部列表.我遇到以下错误:

方法参考中的错误返回类型:无法将java.util.List转换为U

我认为有一个非常简单的方法可以做到这一点,但我找不到它.

该怎么做?

 公共类MyClass实现Comparable< MyClass>{private final int someInt;私人最终List< String>someStrings;公共MyClass(List< String> someStrings,int someInt){this.someInt = someInt;this.someStrings = new ArrayList<>(someStrings);}@Overridepublic int compareTo(MyClass other){返回Comparator.comparing(MyClass :: getSomeInt).thenComparing(MyClass :: getSomeStrings)//错误在这里.compare(this,other);}public int getSomeInt(){返回someInt;}公共列表< String>getSomeStrings(){返回someStrings;}} 

编辑1

我只希望以最简单的方式比较字符串列表(使用隐式 String.compareTo()).

请注意,我现在确实想对我的 List< String> 进行排序,但我希望它是 Comparable ,以便 MyClass 也具有可比性最后,我可以将 MyClass 实例插入到 TreeSet< MyClass> 中.

A在JavaDoc中还看到了以下内容:

  java.util.Comparator< T>公共比较器thenComparing(@NotNull Comparator< ;? super T>其他) 

例如,要根据长度对String的集合进行排序,然后对不区分大小写的自然顺序进行排序,可以使用以下代码来组成比较器,

  Comparator< String>cmp = Comparator.comparingInt(String :: length).thenComparing(String.CASE_INSENSITIVE_ORDER); 

这似乎是一个线索,但我不知道如何将其应用于这个简单的示例.

编辑2

假设我希望按以下方式对我的 List< String> 进行排序:

  • 首先检查: List.size()(短于小于大);
  • 第二次检查大小是否匹配:两个列表的每个元素一一比较,直到找到 String.compareTo 方法返回1或-1的地方.

如何在我的 compareTo 方法中使用lambda做到这一点?

编辑3

这不会重复此问题,因为我想知道如何构建一个包含 List< String> 的类的比较器,其中Java 8链接了 Comparable 调用.

解决方案

因此要比较列表,首先检查长度,然后将两个列表中具有相同索引的每个项目一一比较?

(即 [a,b,c]< [b,a,c] )

为列表字符串的列表返回联接创建自定义比较器:

  Comparator< List< String>>listComparator =(l1,l2)->{如果(l1.size()!= l2.size()){返回l1.size()-l2.size();}for(int i = 0; i< l1.size(); i ++){int strCmp = l1.get(i).compareTo(l2.get(i));如果(strCmp!= 0){返回strCmp;}}返回0;//两个列表相等}; 

然后您可以使用该自定义比较器进行比较:

  @Overridepublic int compareTo(MyClass other){返回Comparator.comparing(MyClass :: getSomeInt).thenComparing(Comparator.comparing(MyClass :: getSomeStrings,listComparator)).compare(this,other);} 

如果您想要 [a,b,c] = [b,a,c] ,那么您必须先对这些列表进行排序,然后再进行比较:

 公共字符串getSomeStringsJoined(){返回getSomeStrings().stream().sort(Comparator.naturalOrder()).collect(Collectors.joining());} 

I have a simple class which stores an integer and a list of Strings.

As I want to use this class in a TreeSet<>, the one must be Comparable. But when trying to use the Java 8 Comparator class, I cannot compare my inner list. I have the following error:

Bad return type in method reference: cannot convert java.util.List to U

I think there is a very simple way to do that but I could not find it out.

How to do that?

public class MyClass implements Comparable<MyClass> {

    private final int          someInt;
    private final List<String> someStrings;

    public MyClass (List<String> someStrings, int someInt) {
        this.someInt = someInt;
        this.someStrings = new ArrayList<>(someStrings);
    }

    @Override
    public int compareTo(MyClass other) {
        return
                Comparator.comparing(MyClass::getSomeInt)
                        .thenComparing(MyClass::getSomeStrings) // Error here
                        .compare(this, other);
    }

    public int getSomeInt() {
        return someInt;
    }

    public List<String> getSomeStrings() {
        return someStrings;
    }
}

Edit 1

I just want the String list to be compared in the simplest way (using implicitly String.compareTo()).

Note that I do now want to sort my List<String> but I want it to be Comparable so that MyClass is also comparable and finally, I can insert MyClass instances into a TreeSet<MyClass>.

A also saw in the JavaDoc the following:

java.util.Comparator<T> public Comparator<T>
    thenComparing(@NotNull Comparator<? super T> other)

For example, to sort a collection of String based on the length and then case-insensitive natural ordering, the comparator can be composed using following code,

Comparator<String> cmp = Comparator.comparingInt(String::length)
   .thenComparing(String.CASE_INSENSITIVE_ORDER);

It seems to be an clue but I don't know how to apply it to this simple example.

Edit 2

Let's say I want my List<String> to be sorted the following way:

  • First check: List.size() (the shorter is less than the larger one);
  • Second check if sizes match: comparing one by one each element of both Lists until finding one where the String.compareTo method returns 1 or -1.

How to do that with lambdas in a my compareTo method?

Edit 3

This does not duplicates this question because I want to know how to build a comparator of a class which contains a List<String> with Java 8 chaining Comparable calls.

解决方案

So to compare the list, first you check the length, then you compare each item with same indexes in both list one by one right?

(That is [a, b, c] < [b, a, c])

Make a custom comparator for list return join of your list string:

Comparator<List<String>> listComparator = (l1, l2) -> {
     if (l1.size() != l2.size()) {
        return l1.size() - l2.size();
     }
     for (int i = 0; i < l1.size(); i++) {
        int strCmp = l1.get(i).compareTo(l2.get(i));
        if (strCmp != 0) {
            return strCmp;
        }
     }
     return 0; // Two list equals
};

Then you can compare using that custom comparator:

@Override
public int compareTo(MyClass other) {
    return  Comparator.comparing(MyClass::getSomeInt)
                    .thenComparing(Comparator.comparing(MyClass:: getSomeStrings , listComparator))
                    .compare(this, other);
}

If you want [a, b, c] = [b, a, c], then you have to sort those list first before comparing:

public String getSomeStringsJoined() {
    return getSomeStrings().stream().sort(Comparator.naturalOrder()).collect(Collectors.joining());
}

这篇关于具有List&lt; String&gt;的可比较类场地的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆