Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中使用比较器逻辑对对象进行排序_Java_Java 8 - Fatal编程技术网

在java中使用比较器逻辑对对象进行排序

在java中使用比较器逻辑对对象进行排序,java,java-8,Java,Java 8,我正在尝试使用以下参数对对象列表进行排序 a、 将partId与另一个对象的id相同的两个列表对象分组 b。将partId为null的任何对象推送到列表的末尾 c。根据计数按升序对分组对象进行排序,首选为 I.组中的两个对象应具有较少的计数 二,。然后,组中的任何对象的计数都少于其他组 以下是我目前掌握的代码 public class ListTTest { public static void main(String[] args) { LstObj lstObj1 =

我正在尝试使用以下参数对对象列表进行排序

a、 将partId与另一个对象的id相同的两个列表对象分组

b。将partId为null的任何对象推送到列表的末尾

c。根据计数按升序对分组对象进行排序,首选为

I.组中的两个对象应具有较少的计数

二,。然后,组中的任何对象的计数都少于其他组

以下是我目前掌握的代码

public class ListTTest {
    public static void main(String[] args) {
        LstObj lstObj1 = new LstObj("0:0:1", "1:0:1", 49);
        LstObj lstObj2 = new LstObj("0:0:2", "1:0:2", 2);
        LstObj lstObj3 = new LstObj("0:2:1", "1:2:1", 0);
        LstObj lstObj4 = new LstObj("0:2:2", null , 0);
        LstObj lstObj5 = new LstObj("0:2:3", "1:2:3" , 2);
        LstObj lstObj6 = new LstObj("0:2:4", "1:2:4" , 49);
        LstObj lstObj7 = new LstObj("1:0:1", "0:0:1" , 49);
        LstObj lstObj8 = new LstObj("1:0:2", "0:0:2" , 49);
        LstObj lstObj9 = new LstObj("1:2:1", "0:2:1" , 0);
        LstObj lstObj10 = new LstObj("1:2:2", null , 0);
        LstObj lstObj11 = new LstObj("1:2:3", "0:2:3" , 49);
        LstObj lstObj12 = new LstObj("1:2:4", "0:2:4" , 49);


        LstObj lst[] = new LstObj[]{lstObj1,lstObj2,lstObj3,lstObj4,lstObj5,lstObj6,lstObj7,lstObj8,lstObj9,lstObj10,lstObj11,lstObj12};
        List<LstObj> lstArr = Arrays.asList(lst);

        lstArr.sort(new Comparator<LstObj>() {
            @Override
            public int compare(LstObj o1, LstObj o2) {
                    if(o1.partId==null){
                        return 1;
                    }else if(o2.partId==null){
                         return -1;
                    }else{
                        return -1*(o1.partId.compareTo(o2.id)-(o1.count-o2.count));
                    }

            }
        });

        System.out.println(lstArr);
    }


}

class LstObj {
    String partId;
    String id;
    int count;

    public LstObj(  String id,
    String partId,
    int count
    ) {
        this.count = count;
        this.partId = partId;
        this.id = id;       
    }

    public String getPartId() {
        return partId;
    }
    public String getId() {
        return id;
    }
    public int getCount() {
        return count;
    }
    public void setPartId(String partId) {
        this.partId = partId;
    }
    public void setId(String id) {
        this.id = id;
    }
    public void setCount(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "LstObj [partId=" + partId + ", id=" + id + ", count=" + count
                + "]\n";
    }


}
但我希望输出为:

 [LstObj [partId=0:2:1, id=1:2:1, count=0]
    , LstObj [partId=1:2:1, id=0:2:1, count=0]
    , LstObj [partId=0:0:2, id=1:0:2, count=2]
    , LstObj [partId=1:0:2, id=0:0:2, count=49]
    , LstObj [partId=0:2:3, id=1:2:3, count=2]
    , LstObj [partId=1:2:3, id=0:2:3, count=49]
    , LstObj [partId=0:0:1, id=1:0:1, count=49]
    , LstObj [partId=1:0:1, id=0:0:1, count=49]
    , LstObj [partId=0:2:4, id=1:2:4, count=49]
    , LstObj [partId=1:2:4, id=0:2:4, count=49]
    , LstObj [partId=null, id=0:2:2, count=0]
    , LstObj [partId=null, id=1:2:2, count=0]

有人知道我到底哪里做错了吗

仅通过查看列表中的两个元素,不可能实现一个应用预期分组逻辑的比较器

您可以执行专用分组操作并对组进行排序,然后创建结果列表。内置分组采集器需要一个函数,该函数能够将每个元素分配给一个组,而不会看到对应的元素,但如果使用稳定的选择器,例如使用
partId
id
中的最小值,则只要输入数据具有正确的形状,正确的元素最终将位于一个组中

List<LstObj> lstArr = Arrays.asList(
    new LstObj("0:0:1", "1:0:1", 49),
    new LstObj("0:0:2", "1:0:2", 2),
    new LstObj("0:2:1", "1:2:1", 0),
    new LstObj("0:2:2", null , 0),
    new LstObj("0:2:3", "1:2:3" , 2),
    new LstObj("0:2:4", "1:2:4" , 49),
    new LstObj("1:0:1", "0:0:1" , 49),
    new LstObj("1:0:2", "0:0:2" , 49),
    new LstObj("1:2:1", "0:2:1" , 0),
    new LstObj("1:2:2", null , 0),
    new LstObj("1:2:3", "0:2:3" , 49),
    new LstObj("1:2:4", "0:2:4" , 49)
);

Function<LstObj,Object> groupFunc = o -> {
    String id = o.getId(), partId = o.getPartId();
    return partId == null? Void.TYPE: partId.compareTo(id)<0? partId: id;
};
List<LstObj> result = lstArr.stream()
        .sorted(Comparator.comparing(LstObj::getPartId, Comparator.nullsLast(null))
                          .thenComparingInt(LstObj::getCount))
        .collect(Collectors.groupingBy(groupFunc, LinkedHashMap::new, Collectors.toList()))
        .values().stream()
        .flatMap(List::stream)
        .collect(Collectors.toList());
System.out.println(result);
List lstArr=Arrays.asList(
新的LstObj(“0:0:1”,“1:0:1”,49),
新的LstObj(“0:0:2”,“1:0:2”,2),
新的LstObj(“0:2:1”,“1:2:1”,0),
新的LstObj(“0:2:2”,空,0),
新的LstObj(“0:2:3”,“1:2:3”,2),
新的LstObj(“0:2:4”,“1:2:4”,49),
新的LstObj(“1:0:1”,“0:0:1”,49),
新的LstObj(“1:0:2”,“0:0:2”,49),
新的LstObj(“1:2:1”,“0:2:1”,0),
新的LstObj(“1:2:2”,空,0),
新的LstObj(“1:2:3”,“0:2:3”,49),
新的LstObj(“1:2:4”,“0:2:4”,49)
);
函数groupFunc=o->{
字符串id=o.getId(),partId=o.getPartId();

return partId==null?Void.TYPE:partId.compareTo(id)仅通过查看列表中的两个元素,不可能实现应用预期分组逻辑的比较器

您可以执行专用分组操作并对组进行排序,然后创建结果列表。内置分组采集器需要一个函数,该函数能够将每个元素分配给一个组,而不会看到对应的元素,但是如果您使用稳定的选择器,例如使用
partId
id,只要您的输入数据具有正确的形状,正确的元素将在一个组中结束

List<LstObj> lstArr = Arrays.asList(
    new LstObj("0:0:1", "1:0:1", 49),
    new LstObj("0:0:2", "1:0:2", 2),
    new LstObj("0:2:1", "1:2:1", 0),
    new LstObj("0:2:2", null , 0),
    new LstObj("0:2:3", "1:2:3" , 2),
    new LstObj("0:2:4", "1:2:4" , 49),
    new LstObj("1:0:1", "0:0:1" , 49),
    new LstObj("1:0:2", "0:0:2" , 49),
    new LstObj("1:2:1", "0:2:1" , 0),
    new LstObj("1:2:2", null , 0),
    new LstObj("1:2:3", "0:2:3" , 49),
    new LstObj("1:2:4", "0:2:4" , 49)
);

Function<LstObj,Object> groupFunc = o -> {
    String id = o.getId(), partId = o.getPartId();
    return partId == null? Void.TYPE: partId.compareTo(id)<0? partId: id;
};
List<LstObj> result = lstArr.stream()
        .sorted(Comparator.comparing(LstObj::getPartId, Comparator.nullsLast(null))
                          .thenComparingInt(LstObj::getCount))
        .collect(Collectors.groupingBy(groupFunc, LinkedHashMap::new, Collectors.toList()))
        .values().stream()
        .flatMap(List::stream)
        .collect(Collectors.toList());
System.out.println(result);
List lstArr=Arrays.asList(
新的LstObj(“0:0:1”,“1:0:1”,49),
新的LstObj(“0:0:2”,“1:0:2”,2),
新的LstObj(“0:2:1”,“1:2:1”,0),
新的LstObj(“0:2:2”,空,0),
新的LstObj(“0:2:3”,“1:2:3”,2),
新的LstObj(“0:2:4”,“1:2:4”,49),
新的LstObj(“1:0:1”,“0:0:1”,49),
新的LstObj(“1:0:2”,“0:0:2”,49),
新的LstObj(“1:2:1”,“0:2:1”,0),
新的LstObj(“1:2:2”,空,0),
新的LstObj(“1:2:3”,“0:2:3”,49),
新的LstObj(“1:2:4”,“0:2:4”,49)
);
函数groupFunc=o->{
字符串id=o.getId(),partId=o.getPartId();

return partId==null?Void.TYPE:partId.compareTo(id)不确定错误在哪里,但您应该看看在Java 8中添加到的方法,例如
comparing()
thencaring()
nullsLast()
。我相信它们可以大大简化您的代码。比较器应该是对称的。类似于
o1.partId.compareTo(o2.id)
的术语是不正确的。此外,通过减号like和
o1.partId.compareTo(o2.id)-(o1.count-o2.count)组合两个比较结果
毫无意义,因为
compareTo
返回的值的大小是完全未指定的(以及假定的结果)。此外,
-1*(…)
是一种冗长的翻转符号方式(
-(…)
也可以),这是反转比较器的一种错误方法。如果比较器的计算结果为
Integer.MIN_VALUE
,则翻转符号会导致溢出,再次导致
Integer.MIN_VALUE
。不确定错误在哪里,但您应该查看添加到Java 8中的方法,例如
比较()
然后比较()
nullsLast()
。我相信它们可以大大简化您的代码。比较器应该是对称的。类似于
o1.partId.compareTo(o2.id)
的术语不可能是正确的。此外,通过减号like和
o1.partId.compareTo(o2.id)-(o1.count-o2.count)组合两个比较结果
毫无意义,因为
compareTo
返回的值的大小是完全未指定的(以及假定的结果)。此外,
-1*(…)
是一种冗长的翻转符号方式(
-(…)
也可以),这是反转比较器的一种坏方法。如果比较器的计算结果为
整数.MIN_值
,则翻转符号会导致溢出,再次导致
整数.MIN_值
。详细解释@Holger,感谢学习指针。上面的代码几乎可以正常工作,但我们如何重新排列组基d关于组中计数的总和?[0,0][1,7][1,6]作为计数,应重新排序为[0,0][1,6][1,7]。您有什么想法吗?然后,您需要在排序后对组进行排序,例如,将上述解决方案的尾部更改为
…values().stream().sorted(Comparator.comparing(l->l.stream().mapToInt(LstObj::getCount()).sum()).flatMap(List::stream).collect(Collectors.toList())
。但是,这将不考虑“
null
partid”约束。当达到这种复杂性时,移除那些特殊对象并在之后重新添加它们将是更简单的选择。是的,这将更简单。感谢您详细的解释@Holger,感谢您的学习指导。上面的代码几乎可以正常工作,但我们如何根据组之间的计数总和重新排序组?[0,0][1,7][1,6]作为计数应重新排序为[0,0][1,6][1,7]。您知道吗?那么,您将