مرتب سازی لیست بر اساس چند معیار

با استفاده از مکانیزم Comparator factory می خواهیم نتیجه مرتب سازی را بدست آوریم.

به شما کلاس Animal به صورت زیر داده می شود:

public class Animal {  
  private String name;
  private int numOfLegs;
  private int numOfWings;  
  public Animal(String name, int numOfLegs, int numOfWings) {
    this.name = name;
    this.numOfLegs = numOfLegs;
    this.numOfWings = numOfWings;
  }  
  … // getters and setters  
  @Override
  public String toString() {
    return name;
  }
}

و این قطعه کد:

List<animal> listOfAnimal = List.of(
  new Animal("Spider", 8, 0),
  new Animal("Fly", 6, 2),
  new Animal("Dragonfly", 6, 4),      
  new Animal("Worm", 0, 0)
);
… // add sorting code here
</animal>

کدام قطعه کد به شما امکان می دهد Animal را به ترتیب زیر مرتب کنید(یکی را انتخاب کن)؟

Worm, Fly, Dragonfly, Spider

A.

listOfAnimal.stream().sorted(Comparator.comparing(a -> a.getNumOfLegs()).thenComparing(a -> a.getNumOfWings())).collect(Collectors.toList());

B.

listOfAnimal.stream().sorted(Comparator.comparing(a -> a.getNumOfWings()).thenComparing(a -> a.getNumOfLegs())).collect(Collectors.toList());

C.

listOfAnimal.stream().sorted(Comparator.comparing(a -> a.getNumOfLegs())).sorted(Comparator.comparing(a -> a.getNumOfWings())).collect(Collectors.toList());

D.

listOfAnimal.sort((la, ra) -> {
  if (la.getNumOfLegs() == ra.getNumOfLegs()) {
    return Integer.compare(la.getNumOfWings(),
                           ra.getNumOfWings());
  } else {
    return Integer.compare(la.getNumOfLegs(),
                           ra.getNumOfLegs());|
  }
});

E. هیچکدام

جواب:

پس کار ما مرتب سازی animal با چندین معیار هست. این خیلی شبیه مرتب سازی لیست از افراد هست که ابتدا بر اساس نام خانوادگی می خواهیم مرتب سازی کنیم و اگر نام خانوادگی با هم یکی بود بعد بر اساس نام مرتب سازی انجام شود.

در این مورد شما ابتدا باید بر اساس تعداد leg مرتب سازی را انجام دهید و اگر تعداد leg با هم برابر بود بر اساس wings مرتب سازی کنید.

گزینه A وسوسه انگیز به نظر می رسد. از مکانیزم های factory در Comparator به گونه ای استفاده می کند که نشان می دهد ابتدا بر اساس تعداد legs مرتب شده و سپس بر اساس تعداد wings. با این حال زمانی که شما به صورت زنجیر وارد از این تابع استفاده می کنید، لیستی که برگشت داده می شود از نوع Animal نخواهد بود و یک لیست از نوع Object برگردانده می شود. برای همین تابع های getNumOfLegs یا getNumOfWings را ندارد. در نتیجه مورد A درست نمی باشد.

به هر حال شما می توانید کد A را به صورت زیر درست کنید:

listOfAnimal.stream().sorted(Comparator.comparing((Animal a) -> a.getNumOfLegs()).thenComparing((Animal a) -> a.getNumOfWings())).collect(Collectors.toList());

گزینه B به دو دلیل درست نیست.

  1. مرتب سازی را ابتدا بر اساس wings انجام داده سپس بر اساس legs
  2. همچنین مشکلی که گزینه A داشت را این گزینه هم دارد.

گزینه C دو تا مرتب سازی جدا از هم هست. به این صورت که ابتدا بر اساس legs لیست مرتب می شود و بعد لیست بر اساس wings مرتب می شود. در واقع نتیجه مثل گزینه B هست. پس این گزینه هم درست نیست.

به یاد داشته باشید که عملیات مرتب سازی از نظر محاسباتی پر هزینه هستند، بنابراین در صورت امکان، از انجام دو کار خودداری کنید.

گزینه D به دلیل اینکه List.sort لیست اصلی را تغییر می دهد و لیست بر اساس List.of ساخته شده است و لیستی که این گونه ساخته می شود نمی تواند تغییر کند اشتباه است و خطای java.lang.UnsupportedOperationException را می گیرد.

اگر لیست تغییر پذیر بود این گزینه درست بود. مثلا اگر لیست به صورت زیر ساخته شده بود:

listOfAnimal = new ArrayList<>(listOfAnimal);

در نتیجه بر اساس مواردی که گفته شد گزینهای A,B,C,D اشتباه بودن و پس گزینه E درست است.

نتیجه: گزینه E درست است.

دیدگاهتان را بنویسید