날짜별로 ArrayList의 객체를 정렬 하시겠습니까?


149

내가 찾은 모든 예는 알파벳순 으로이 작업을 수행하는 반면 날짜별로 정렬 된 요소가 필요합니다.

내 ArrayList에는 데이터 멤버 중 하나가 DateTime 개체 인 개체가 포함되어 있습니다. DateTime에서 함수를 호출 할 수 있습니다.

lt() // less-than
lteq() // less-than-or-equal-to

그래서 비교하려면 다음과 같이 할 수 있습니다.

if(myList.get(i).lt(myList.get(j))){
    // ...
}

if 블록 안에서 무엇을해야합니까?


3
솔루션을 게시했지만 주문에 대한 통찰력을 얻으려면 주문 알고리즘 (버블 정렬, 병합 정렬, 빠른 정렬 등)에 대해 읽어야합니다.
helios

고마워, 나는 이것들을 살펴볼 것이다, 나는 정렬에 대해 아무것도 모른다

여러 유용한 자바 1.8 솔루션은이 스레드에서 볼 수 있습니다 : stackoverflow.com/questions/36361156/...을
lradacher

답변:


417

객체를 비슷하게 만들 수 있습니다.

public static class MyObject implements Comparable<MyObject> {

  private Date dateTime;

  public Date getDateTime() {
    return dateTime;
  }

  public void setDateTime(Date datetime) {
    this.dateTime = datetime;
  }

  @Override
  public int compareTo(MyObject o) {
    return getDateTime().compareTo(o.getDateTime());
  }
}

그런 다음 다음을 호출하여 정렬합니다.

Collections.sort(myList);

그러나 때로는 여러 다른 속성을 정렬하려는 경우와 같이 모델을 변경하지 않으려는 경우가 있습니다. 이 경우 즉시 비교기를 만들 수 있습니다.

Collections.sort(myList, new Comparator<MyObject>() {
  public int compare(MyObject o1, MyObject o2) {
      return o1.getDateTime().compareTo(o2.getDateTime());
  }
});

그러나 위의 내용은 비교할 때 dateTime이 null이 아닌 경우에만 작동합니다. NullPointerException을 피하기 위해 null을 처리하는 것이 현명합니다.

public static class MyObject implements Comparable<MyObject> {

  private Date dateTime;

  public Date getDateTime() {
    return dateTime;
  }

  public void setDateTime(Date datetime) {
    this.dateTime = datetime;
  }

  @Override
  public int compareTo(MyObject o) {
    if (getDateTime() == null || o.getDateTime() == null)
      return 0;
    return getDateTime().compareTo(o.getDateTime());
  }
}

또는 두 번째 예에서 :

Collections.sort(myList, new Comparator<MyObject>() {
  public int compare(MyObject o1, MyObject o2) {
      if (o1.getDateTime() == null || o2.getDateTime() == null)
        return 0;
      return o1.getDateTime().compareTo(o2.getDateTime());
  }
});

1
좋은 대답입니다. 널 검사없이 버전을 포함해야하는 이유는 무엇입니까? 장점은 무엇입니까? 올바른 방법이 두 번째 방법이라면 포함하고 중요한 정보를 더 매력적으로 만들 수 있습니다.
amotzg

17
두 가지 이유-단순성과 빠른 실패. 코드를 가능한 한 간단하게 만들고 싶을 때 속성이 null이 아니어야하는 경우 null이 발생하면 가능한 한 빨리 코드가 실패하고 잘못된 데이터를 전달하고 그 자리에서 더 멀어지기를 원할 것입니다 유효하지 않은 데이터가 도입 된 위치
Domchi

3
o1 또는 o2가 null이면 0을 반환합니다. // 0을 반환하면 같음을 의미하므로이 줄은 버그를 일으킬 수 있습니다.
tanyehzheng

@tanyehzheng, 맞습니다. 오해의 소지가 있지만 정렬에 사용되는 .compareTo ()와 .equals ()에는 차이가 있습니다. 정렬 중에 null을 처리하는 방법에 실제로 달려 있습니다.
Domchi

1
각 날짜의 null을 개별적으로 확인하고 원하는대로 정렬해야합니다 (시퀀스의 시작 또는 끝에서 null 정렬). 즉, 하나의 날짜가 널이고 다른 날짜가 널이 아닌 경우 1 또는 -1을 리턴하십시오. 그렇게하지 않으면, 널은 정렬되지 않고 정렬 이전에 목록에 있었던 모든 위치에 남아 있습니다.
droozen

64

Java 8부터 List 인터페이스는 정렬 방법을 제공합니다 . 람다 식과 결합 하면 가장 쉬운 해결책은

// sort DateTime typed list
list.sort((d1,d2) -> d1.compareTo(d2));
// or an object which has an DateTime attribute
list.sort((o1,o2) -> o1.getDateTime().compareTo(o2.getDateTime()));
// or like mentioned by Tunaki
list.sort(Comparator.comparing(o -> o.getDateTime()));

역 분류

Java 8에는 역 정렬을위한 편리한 방법도 있습니다.

//requested by lily
list.sort(Comparator.comparing(o -> o.getDateTime()).reversed());

8
더 나은 것list.sort(Comparator.comparing(o -> o.getDateTime()));
Tunaki

21
이것에 대해 :list.sort(Comparator.comparing(MyObject::getDateTime)
whitebrow

@Tunaki는 역 정렬을 수행하는 방법?
백합

18

Collections.sort 메소드를 사용할 수 있습니다. 정적 방법입니다. 리스트와 비교기를 전달합니다. 목록에 대해 수정 된 병합 정렬 알고리즘을 사용합니다. 그렇기 때문에 쌍 비교를 수행하려면 비교기를 전달해야합니다.

Collections.sort(myList, new Comparator<MyObject> {
   public int compare(MyObject o1, MyObject o2) {
      DateTime a = o1.getDateTime();
      DateTime b = o2.getDateTime();
      if (a.lt(b)) 
        return -1;
      else if (a.lteq(b)) // it's equals
         return 0;
      else
         return 1;
   }
});

myList가 비교 가능한 유형 (Comparable 인터페이스를 구현하는 유형) (예 : 날짜, 정수 또는 문자열) 인 경우 비교기를 생략하면 자연 순서가 사용됩니다.


1
그리고 이것이 끝나면 myList를 반환합니까?

myList를 수정합니다. 그래서 그것이 끝날 때 정렬
helios

@ 슬 레드 : download.oracle.com/javase/6/docs/api/java/util/… , java.util.Comparator)
helios

9
list.sort(Comparator.comparing(o -> o.getDateTime()));

Java 8 람다를 사용하는 Tunaki의 가장 좋은 답변 IMHO


8

감안할 때 MyObject가 그 DateTime로모그래퍼 회원을 getDateTime()방법, 당신은 정렬 할 수 있습니다 ArrayList포함 된 MyObject바이 요소 DateTime같은 객체를 :

Collections.sort(myList, new Comparator<MyObject>() {
    public int compare(MyObject o1, MyObject o2) {
        return o1.getDateTime().lt(o2.getDateTime()) ? -1 : 1;
    }
});

현재 시스템 시간을 기준으로 주문하려면 어떻게해야합니까?
사용자 3

5

이것이 내가 해결 한 방법입니다.

Collections.sort(MyList, (o1, o2) -> o1.getLastModified().compareTo(o2.getLastModified()));

그것이 당신을 돕기를 바랍니다.


날짜별로 뒤집는 방법?
좀비

2

Java 1.8이 도입되면서 스트림은 이러한 종류의 문제를 해결하는 데 매우 유용합니다.

Comparator <DateTime> myComparator = (arg1, arg2) 
                -> {
                    if(arg1.lt(arg2)) 
                       return -1;
                    else if (arg1.lteq(arg2))
                       return 0;
                    else
                       return 1;
                   };

ArrayList<DateTime> sortedList = myList
                   .stream()
                   .sorted(myComparator)
                   .collect(Collectors.toCollection(ArrayList::new));

1

여기에있는 모든 대답은 간단한 문제 (적어도 경험이없는 Java 개발자에게는 필요하지 않음)에 대해 불필요하게 복잡하다는 것을 알았습니다. 나는 비슷한 문제가 있었고이 (및 다른) 솔루션에 대해 기회를 얻었으며 포인터를 제공했지만 초보자에게 위에서 언급 한 것처럼 발견했습니다. 내 솔루션은 날짜가 객체의 어디에 있는지에 따라 다릅니다.이 경우 날짜는 Object []의 첫 번째 요소입니다. 여기서 dataVector 는 객체를 포함하는 ArrayList입니다.

Collections.sort(dataVector, new Comparator<Object[]>() {
    public int compare(Object[] o1, Object[] o2) {
        return ((Date)o1[0]).compareTo(((Date)o2[0]));
    }
});

6
귀하의 답변이 다른 답변보다 덜 복잡하거나 더 정확합니까? 내 의견으로는 WhiteFang32의 대답은 매우 유사하고 간결합니다.
amotzg

잠시 동안 떨어져서 응답을 보지 못했지만 다시는 늦지 않는 것이 낫습니다. WhiteFang의 대답의 간결함은 경험이 부족한 Java 개발자의 눈에 대한 단점이라고 생각합니다! 내 응답에 타입 캐스팅을 포함시키는 것은 클린 처였습니다 (적어도 내 마음에는). 남은 것은 내 대답이 다른 것보다 더 정확하다는 주장을 푼 곳은 어디입니까? 나는 증기를 내버려 두었다.. 모두는 용서 받았다!
Nepaluz

o.getDateTime ()은 타이핑에 관한 것이 아니라 DateTime다른 객체 안에 포함 된 객체 에 대한 OP의 설명에 관한 것입니다. 그것이 유일한 것이 Date거나 DateTime물건이라면 처음에는를 Comparable필요로하지 않았습니다 Comparator.
amotzg 2018 년

당신의 대답이 덜 정확하거나 그렇지 않다고 말하는 것은 아닙니다. 나는 단지 내가 더 잘 이해할 수 있도록 정보를 찾고있었습니다. 그렇지 않은 것 같으면 미안합니다.
amotzg

0

이 오래된 응답 할 수 있지만, 나는 정렬 할 것 비교기 만들려면이 게시물에서 몇 가지 예를 사용하는 ArrayList의를 HashMap<String, String>타임 스탬프 인 것을, 목록에서 하나의 객체로한다.

나는이 물건들을 가지고있다 :

ArrayList<Map<String, String>> alList = new ArrayList<Map<String, String>>();

지도 객체는 다음과 같습니다.

Map<String, Object> map = new HashMap<>();
        // of course this is the actual formatted date below in the timestamp
        map.put("timestamp", "MM/dd/yyyy HH:mm:ss"); 
        map.put("item1", "my text goes here");
        map.put("item2", "my text goes here");

이 매핑은 alList.add(map)루프 내 에서 함수를 사용하여 모든 객체를 배열 목록에로드하는 데 사용됩니다 .

이제 나는 내 자신의 비교기를 만들었습니다.

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

 public class DateSorter implements Comparator {
     public int compare(Object firstObjToCompare, Object secondObjToCompare) {
    String firstDateString = ((HashMap<String, String>) firstObjToCompare).get("timestamp");
    String secondDateString = ((HashMap<String, String>) secondObjToCompare).get("timestamp");

    if (secondDateString == null || firstDateString == null) {
        return 0;
    }

    // Convert to Dates
    DateTimeFormatter dtf = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
    DateTime firstDate = dtf.parseDateTime(firstDateString);
    DateTime secondDate = dtf.parseDateTime(secondDateString);

    if (firstDate.isAfter(secondDate)) return -1;
    else if (firstDate.isBefore(secondDate)) return 1;
    else return 0;
    }
}

이제 배열에서 언제든지 Comparator를 호출 할 수 있으며 배열을 정렬하여 위치 0의 최신 타임 스탬프 (목록 맨 위)와 목록 끝의 가장 빠른 타임 스탬프를 제공합니다. 기본적으로 새로운 게시물이 맨 위에 표시됩니다.

Collections.sort(alList, new DateSorter());

이것은 누군가를 도울 수 있기 때문에 내가 게시 한 이유입니다. compare () 함수 내에서 return 문을 고려하십시오. 3 가지 유형의 결과가 있습니다. 동일한 경우 0을 리턴하고 첫 번째 날짜가 두 번째 날짜 이전 인 경우> 0을 리턴하고 첫 번째 날짜가 두 번째 날짜 이후 인 경우 <0을 리턴합니다. 목록을 뒤집으려면 두 반환 문을 바꾸십시오! 단순 =]


이에 대한 의견을 추가하고 싶었습니다. 물론 배열 목록을 처리 할 때 "NullPointerExceptions"가 있습니다 (반환 0 문 제공). 각 케이스가 다르므로 처리해야합니다. 예를 들어 객체가 0 인 목록은 NullPointerException을 생성하거나 객체가 1 인 목록을 생성합니다!
Brandon

0

ArrayList In 인수를 전달하십시오.

    private static void order(ArrayList<Object> list) {

    Collections.sort(list, new Comparator() {

        public int compare(Object o2, Object o1) {

            String x1 =  o1.Date;
            String x2 =  o2.Date;

                return  x1.compareTo(x2);

        }
    });
}

0

아래 방법을 사용하여 날짜가 정렬되어 있는지 확인하십시오.

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");

boolean  decendingOrder = true;
    for(int index=0;index<date.size() - 1; index++) {
        if(simpleDateFormat.parse(date.get(index)).getTime() < simpleDateFormat.parse(date.get(index+1)).getTime()) {
            decendingOrder = false;
            break;
        }
    }
    if(decendingOrder) {
        System.out.println("Date are in Decending Order");
    }else {
        System.out.println("Date not in Decending Order");
    }       
}   

1
질문에 대답하지 않는 것 같습니다. 그리고 젊은이들에게 오래되고 악명 높은 번잡 한 SimpleDateFormat수업 을 사용하도록 가르치지 마십시오 . 적어도 첫 번째 옵션은 아닙니다. 그리고 예약 없이는 아닙니다. 오늘날 우리는 java.time최신 Java 날짜 및 시간 API 와 그 기능 이 훨씬 뛰어납니다 DateTimeFormatter.
Ole VV

0

Date 클래스는 이미 Comparator 인터페이스를 구현합니다. 아래 수업이 있다고 가정합니다.

public class A {

    private Date dateTime;

    public Date getDateTime() {
        return dateTime;
    }

    .... other variables

}

그리고 A 객체 목록이 있다고 가정하면 List<A> aListJava 8의 스트림 API (아래 스 니펫)로 쉽게 정렬 할 수 있습니다.

import java.util.Comparator;
import java.util.stream.Collectors;

...

aList = aList.stream()
        .sorted(Comparator.comparing(A::getDateTime))
        .collect(Collectors.toList())

-1

미래의 시청자들에게는 이것이 가장 간단한 해결책이라고 생각합니다. 모델에 문자열 유형 날짜 (예 : "2020-01-01 10:00:00")가 포함 된 경우 다음 줄을 작성하여 데이터를 다음 날짜부터 내림차순으로 정렬하십시오 가장 오래된 것에서 가장 새로운 것 :

Collections.sort(messages, (o1, o2) -> o2.getMessageDate().compareTo(o1.getMessageDate()));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.