development

속성별로 사용자 지정 개체의 ArrayList 정렬

big-blog 2020. 9. 27. 13:03
반응형

속성별로 사용자 지정 개체의 ArrayList 정렬


Comparator를 사용하여 ArrayLists 정렬에 대해 읽었지만 사람들이 사용한 모든 예제 compareTo에서 일부 연구에 따르면 Strings 메서드입니다.

사용자 지정 개체의 ArrayList를 속성 중 하나 인 Date 개체 ( getStartDay()) 로 정렬하고 싶었습니다 . 일반적으로 나는 그들을 비교하기 item1.getStartDate().before(item2.getStartDate())때문에 다음과 같이 쓸 수 있는지 궁금합니다.

public class CustomComparator {
    public boolean compare(Object object1, Object object2) {
        return object1.getStartDate().before(object2.getStartDate());
    }
}

public class RandomName {
    ...
    Collections.sort(Database.arrayList, new CustomComparator);
    ...
}

Date구현 하기 때문에 Comparable동일한 compareTo방법 String이 있습니다.

따라서 사용자 정의 Comparator는 다음과 같이 보일 수 있습니다.

public class CustomComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
}

compare()방법은 반환해야 int당신이 직접 반환하지 수 있도록, boolean어쨌든 기획 것처럼.

정렬 코드는 다음과 같이 작성했습니다.

Collections.sort(Database.arrayList, new CustomComparator());

비교기를 재사용 할 필요가 없다면이 모든 것을 작성하는 약간 더 짧은 방법은 인라인 익명 클래스로 작성하는 것입니다.

Collections.sort(Database.arrayList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
});

이후

이제 람다 식사용하여 더 짧은 형식으로 마지막 예제를 작성할 수 있습니다 Comparator.

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

그리고 Listsort(Comparator)당신이 더욱이를 단축 할 수 있도록 방법 :

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

이것은 키가 있는 클래스에 대한를 생성하는 내장 메서드 가있는 일반적인 관용구입니다 .ComparatorComparable

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));

이들 모두는 동등한 형태입니다.


자연 정렬 순서 (예 : 클래스 번호)가있는 클래스는 Comparable 인터페이스를 구현해야하며, 자연 정렬 순서가없는 클래스 (예 : Chair 클래스)에는 Comparator (또는 익명 Comparator)가 제공되어야합니다. 수업).

두 가지 예 :

public class Number implements Comparable<Number> {
    private int value;

    public Number(int value) { this.value = value; }
    public int compareTo(Number anotherInstance) {
        return this.value - anotherInstance.value;
    }
}

public class Chair {
    private int weight;
    private int height;

    public Chair(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }
    /* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getWeight() - chair2.getWeight();
    }
}
class ChairHeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getHeight() - chair2.getHeight();
    }
}

용법:

List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);

List<Chair> chairs = new ArrayList<Chair>();
// Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
// Sort by height:
Collections.sort(chairs, new ChairHeightComparator());

// You can also create anonymous comparators;
// Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
    public int compare(Chair chair1, Chair chair2) {
        ...
    }
});

정렬을 ArrayList위해 다음 코드 스 니펫을 사용할 수 있습니다.

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});

그래 넌 할수있어. 항목을 비교하는 데는 Comparable 인터페이스와 Comparator 인터페이스의 두 가지 옵션이 있습니다.

이 두 인터페이스는 서로 다른 동작을 허용합니다. Comparable을 사용하면 방금 설명한 Strings (사실 String이 Comparable을 구현 함)처럼 객체가 작동하도록 만들 수 있습니다. 두 번째, Comparator를 사용하면 요청한 작업을 수행 할 수 있습니다. 다음과 같이 할 수 있습니다.

Collections.sort(myArrayList, new MyComparator());

그러면 Collections.sort 메서드가 정렬 메커니즘에 대해 비교기를 사용하게됩니다. ArrayList의 객체가 비교 가능을 구현하는 경우 대신 다음과 같이 할 수 있습니다.

Collections.sort(myArrayList);

컬렉션 클래스는이 유용한 일반적인 도구를 포함하고 있습니다.


JAVA 8 람다 식

Collections.sort(studList, (Student s1, Student s2) ->{
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});

또는

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)

Java 8에서는 비교기에 대한 메서드 참조를 사용할 수 있습니다.

import static java.util.Comparator.comparing;

Collections.sort(list, comparing(MyObject::getStartDate));

기술이 매일 나타나기 때문에 답은 시간이 지나면 바뀔 것입니다. LambdaJ를 살펴 보니 매우 흥미로워 보입니다.

LambdaJ를 사용 하여 이러한 작업을 해결해 볼 수 있습니다 . 여기에서 찾을 수 있습니다. http://code.google.com/p/lambdaj/

여기에 예가 있습니다.

반복 정렬

List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
});

람다로 정렬

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

물론 이런 아름다움은 성능에 영향을 주지만 (평균 2 배) 더 읽기 쉬운 코드를 찾을 수 있습니까?


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

public class test {

public static class Person {
    public String name;
    public int id;
    public Date hireDate;

    public Person(String iname, int iid, Date ihireDate) {
        name = iname;
        id = iid;
        hireDate = ihireDate;
    }

    public String toString() {
        return name + " " + id + " " + hireDate.toString();
    }

    // Comparator
    public static class CompId implements Comparator<Person> {
        @Override
        public int compare(Person arg0, Person arg1) {
            return arg0.id - arg1.id;
        }
    }

    public static class CompDate implements Comparator<Person> {
        private int mod = 1;
        public CompDate(boolean desc) {
            if (desc) mod =-1;
        }
        @Override
        public int compare(Person arg0, Person arg1) {
            return mod*arg0.hireDate.compareTo(arg1.hireDate);
        }
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SimpleDateFormat df = new SimpleDateFormat("mm-dd-yyyy");
    ArrayList<Person> people;
    people = new ArrayList<Person>();
    try {
        people.add(new Person("Joe", 92422, df.parse("12-12-2010")));
        people.add(new Person("Joef", 24122, df.parse("1-12-2010")));
        people.add(new Person("Joee", 24922, df.parse("12-2-2010")));
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    Collections.sort(people, new Person.CompId());
    System.out.println("BY ID");
    for (Person p : people) {
        System.out.println(p.toString());
    }

    Collections.sort(people, new Person.CompDate(false));
    System.out.println("BY Date asc");
    for (Person p : people) {
        System.out.println(p.toString());
    }
    Collections.sort(people, new Person.CompDate(true));
    System.out.println("BY Date desc");
    for (Person p : people) {
        System.out.println(p.toString());
    }

}

}

JAVA 8을 사용하는 가장 쉬운 방법은 영어 알파벳 정렬입니다.

클래스 구현

public class NewspaperClass implements Comparable<NewspaperClass>{
   public String name;

   @Override
   public int compareTo(NewspaperClass another) {
      return name.compareTo(another.name);
   }
}

종류

  Collections.sort(Your List);

영어가 아닌 문자가 포함 된 알파벳을 정렬하려면 로케일을 사용할 수 있습니다. 아래 코드는 터키어 문자 정렬을 사용합니다.

클래스 구현

public class NewspaperClass implements Comparator<NewspaperClass> {
   public String name;
   public Boolean isUserNewspaper=false;
   private Collator trCollator = Collator.getInstance(new Locale("tr_TR"));



   @Override
   public int compare(NewspaperClass lhs, NewspaperClass rhs) {
      trCollator.setStrength(Collator.PRIMARY);
      return trCollator.compare(lhs.name,rhs.name);
   }
}

종류

Collections.sort(your array list,new NewspaperClass());

기능 및 방법 참조

Collections.sort방법은 당신이 패스를 List사용하여 정렬 할 수 있습니다 Comparator. Comparator사용하여 구현 될 수있는 Comparator.comparing사용자가 전달할 수있는 방법 에있어서의 참조 필요한 등을 Function. 다행히 실제 코드는이 설명보다 훨씬 간단하고 짧습니다.

Java 8의 경우 :

Collections.sort(list, comparing(ClassName::getName));

또는

Collections.sort(list, comparing(ClassName::getName).reversed());

또 다른 방법은

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));

Java 8이후로 우리는 Collections.sort()직접 사용할 필요가 없습니다 . List인터페이스에는 기본 sort()방법이 있습니다.

List<User> users = Arrays.asList(user1,user2,user3);
users.sort( (u1, u2) -> { 
return u1.getFirstName.compareTo(u2.getFirstName());}); 

http://visvv.blogspot.in/2016/01/sorting-objects-in-java-8.html을 참조하십시오 .


Bean Comparator사용 하여 사용자 정의 클래스의 모든 속성을 정렬 할 수 있습니다 .


예, 예를 들어이 답변v 에서 클래스 의 속성별로 정렬 할 수 있습니다.IndexValue

    // Sorting by property v using a custom comparator.
    Arrays.sort( array, new Comparator<IndexValue>(){
        public int compare( IndexValue a, IndexValue b ){
            return a.v - b.v;
        }
    });

여기서 눈치 채면 익명의 내부 클래스 (클로저 용 Java)를 만들고 sort클래스 메서드에 직접 전달합니다.Arrays

당신의 객체는 또한 구현할 수 Comparable있지만 (그것이 자바의 String과 대부분의 핵심 라이브러리가하는 일이다)하지만 그것은 자체적으로 클래스의 "자연적인 정렬 순서"를 정의하고 새로운 것을 연결하는 것을 허용하지 않는다.


Guava Ordering을 사용해 볼 수 있습니다 .

Function<Item, Date> getStartDate = new Function<Item, Date>() {
    public Date apply(Item item) {
        return item.getStartDate();
    }
};

List<Item> orderedItems = Ordering.natural().onResultOf(getStartDate).
                          sortedCopy(items);

Java 8 Lambda는 정렬을 단축합니다.

Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));

Java 8을 사용하여 정렬 할 수 있습니다.

yourList.sort(Comparator.comparing(Classname::getName));

or

yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));

이 답변 중 전부는 아니지만 대부분은 기본 클래스 (Object)에 의존하여 비교 가능하거나 도우미 비교 가능한 인터페이스를 갖습니다.

내 솔루션이 아닙니다! 다음 코드를 사용하면 문자열 이름을 알고 객체의 필드를 비교할 수 있습니다. 이름을 사용하지 않도록 쉽게 수정할 수 있지만,이를 노출하거나 비교할 대상 중 하나를 구성해야합니다.

Collections.sort(anArrayListOfSomeObjectPerhapsUsersOrSomething, new ReflectiveComparator(). new ListComparator("name"));

public class ReflectiveComparator {
    public class FieldComparator implements Comparator<Object> {
        private String fieldName;

        public FieldComparator(String fieldName){
            this.fieldName = fieldName;
        }

        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);

                Comparable object1FieldValue = (Comparable) field.get(object1);
                Comparable object2FieldValue = (Comparable) field.get(object2);

                return object1FieldValue.compareTo(object2FieldValue);
            }catch (Exception e){}

            return 0;
        }
    }

    public class ListComparator implements Comparator<Object> {
        private String fieldName;

        public ListComparator(String fieldName) {
            this.fieldName = fieldName;
        }

        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Comparable o1FieldValue = (Comparable) field.get(object1);
                Comparable o2FieldValue = (Comparable) field.get(object2);

                if (o1FieldValue == null){ return -1;}
                if (o2FieldValue == null){ return 1;}
                return o1FieldValue.compareTo(o2FieldValue);
            } catch (NoSuchFieldException e) {
                throw new IllegalStateException("Field doesn't exist", e);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Field inaccessible", e);
            }
        }
    }
}

이 코드 조각이 유용 할 수 있습니다. 제 경우에 오브젝트를 정렬하려면 VolumeName으로 정렬하고 싶습니다.

public List<Volume> getSortedVolumes() throws SystemException {
    List<Volume> volumes = VolumeLocalServiceUtil.getAllVolumes();
    Collections.sort(volumes, new Comparator<Volume>() {
        public int compare(Volume o1, Volume o2) {
            Volume p1 = (Volume) o1;
            Volume p2 = (Volume) o2;
            return p1.getVolumeName().compareToIgnoreCase(
                    p2.getVolumeName());
        }
    });
    return volumes;
}

작동합니다. 내 jsp에서 사용합니다.


2016 년 독일 슈투트가르트에서 열린 자바 포럼 에서이 프레젠테이션 홀드를 살펴볼 수 있습니다 .

몇 개의 슬라이드 만이 독일어를 사용하며 콘텐츠의 99 %는 "영어 기반"Java 소스 코드입니다. 처럼

someCollection.sort(
  OurCustomComparator
    .comparing(Person::getName)
    .thenComparing(Person::getId)
);

OurCustomComparator기본 방법 (및 기타 흥미로운 아이디어)을 사용하는 입니다. 표시된대로 정렬을위한 getter 메소드를 선택하는 매우 간결한 코드로 이어집니다. 정렬 기준의 매우 간단한 체인 (또는 반전).

java8을 사용하는 경우 시작하는 데 필요한 많은 자료를 찾을 수 있습니다.


1.8 이후의 새로운 기능은 Collection.sort ()를 사용하는 대신 List.sort () 메서드이므로 mylistcontainer.sort ()를 직접 호출합니다.

다음은 List.sort () 기능을 보여주는 코드 스 니펫입니다.

List<Fruit> fruits = new ArrayList<Fruit>();
fruits.add(new Fruit("Kiwi","green",40));
fruits.add(new Fruit("Banana","yellow",100));
fruits.add(new Fruit("Apple","mixed green,red",120));
fruits.add(new Fruit("Cherry","red",10));

// a) using an existing compareto() method
fruits.sort((Fruit f1,Fruit f2) -> f1.getFruitName().compareTo(f2.getFruitName()));
System.out.println("Using String.compareTo(): " + fruits);
//Using String.compareTo(): [Apple is: mixed green,red, Banana is: yellow, Cherry is: red, Kiwi is: green]

// b) Using a comparable class
fruits.sort((Fruit f1,Fruit f2) -> f1.compareTo(f2));  
System.out.println("Using a Comparable Fruit class (sort by color): " + fruits);
// Using a Comparable Fruit class (sort by color): [Kiwi is green, Apple is: mixed green,red, Cherry is: red, Banana is: yellow]

Fruit 클래스는 다음과 같습니다.

public class Fruit implements Comparable<Fruit>
{
    private String name;
    private String color;
    private int quantity;

    public Fruit(String name,String color,int quantity)
    { this.name = name; this.color = color; this.quantity = quantity; }

    public String getFruitName() { return name; }        
    public String getColor() { return color; }  
    public int getQuantity() { return quantity; }

    @Override public final int compareTo(Fruit f) // sorting the color
    {
        return this.color.compareTo(f.color);
    }     
    @Override public String toString()
    {   
        return (name + " is: " + color);
    }
} // end of Fruit class   

customComparator 클래스를 사용하려면 java.util.Comparator를 구현해야합니다. 또한 compare () AND equals ()를 재정의해야합니다.

compare ()는 다음 질문에 답해야합니다. 객체 1이 객체 2보다 작거나 같거나 큰가요?

전체 문서 : http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html


여기 에서이 라이브러리를 사용 하여 여러 열에서 사용자 지정 개체 목록을 정렬 할 수 있습니다. 라이브러리는 버전 8.0 기능을 사용합니다. 샘플도 거기에서 사용할 수 있습니다. 다음은 수행 할 샘플입니다.

SortKeys sortKeys = new SortKeys();
sortKeys.addField("firstName")
            .addField("age", true); // This (true) will sort the age descending

// Other ways to specify a property to the sorter are
//      .addField("lastName", String.class);
//      .addField("dob", Date.class, true);

// Instantiate a ListSorter
ListSorter listSorter = new ListSorter();

// Pass the data to sort (listToSort) and the "by keys" to sort (sortKeys)
List sortedList = (List<Person>) listSorter.sortList(listToSort, sortKeys);

이 프로세스를 선호합니다.

public class SortUtil
{    
    public static <T> List<T> sort(List<T> list, String sortByProperty)
    {
            Collections.sort(list, new BeanComparator(sortByProperty));
            return list;
    }
}

List<T> sortedList = SortUtil<T>.sort(unsortedList, "startDate");

객체 목록에라는 속성이있는 경우 startDateuse this를 반복해서 호출합니다. 그들을 연결할 수도 있습니다 startDate.time.

이것은로 개체를 필요로 Comparable당신이 필요로하는 수단 compareTo, equalshashCode구현.

예, 더 빠를 수 있습니다 ...하지만 이제 각 유형에 대해 새로운 비교기를 만들 필요가 없습니다. 개발 시간을 절약하고 런타임을 포기할 수 있다면 이것으로 갈 수 있습니다.


Java 8 사용을 사용하면 다음을 Comparator사용하여 한 줄로 정의 할 수 있습니다.Comparator.comparing()

다음 방법 중 하나를 사용하십시오.

옵션 1:

listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));

옵션 2 :

Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));

사용자 정의 클래스는 CompareTo 메서드 구현이 필요한 "Comparable"인터페이스를 구현할 수 있습니다. CompareTo 메서드에서 개체가 다른 개체 보다 작거나 많다는 의미를 정의 할 수 있습니다 . 따라서 귀하의 예에서는 다음과 같이 보일 수 있습니다.

public class MyCustomClass implements Comparable<MyCustomClass>{

..........

 @Override
public int compareTo(MyCustomClass a) {
    if(this.getStartDate().before(a.getStartDate())){
        return -1;
    }else if(a.getStartDate().before(this.getStartDate())){
        return 1;
    }else {
        return 0;
    }
}

음의 수는 것을 나타낸다 비교되는 오브젝트보다 작다. 양수는 이것이 비교 대상 개체보다 크다는 것을 나타내고 0은 개체가 같음을 의미합니다.

그런 다음 collections.sort (myList)를 사용하여 비교기를 입력하지 않고도 목록을 정렬 할 수 있습니다. 이 방법은 TreeSet 또는 TreeMap과 같은 정렬 된 컬렉션 데이터 구조를 사용하는 경우 자동으로 정렬되는 장점도 있습니다.

Comparable 인터페이스에 대한 자세한 내용을 읽으려면이 기사를 확인할 수 있습니다 (공개 : I am the author;)) https://nullbeans.com/the-java-comparable-interface-automatic-sort-of-collections/

참고 URL : https://stackoverflow.com/questions/2784514/sort-arraylist-of-custom-objects-by-property

반응형