เรียงลำดับวัตถุใน ArrayList ตามวันที่หรือไม่


149

ทุกตัวอย่างที่ฉันพบคือการทำตามตัวอักษรในขณะที่ฉันต้องการเรียงตามวันที่

My ArrayList มีวัตถุที่หนึ่งใน datamembers เป็นวัตถุ DateTime ใน DateTime ฉันสามารถเรียกใช้ฟังก์ชั่น:

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

ดังนั้นเพื่อเปรียบเทียบฉันสามารถทำสิ่งที่ชอบ:

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

ฉันควรทำอย่างไรในบล็อก if


3
ฉันโพสต์โซลูชัน แต่ถ้าคุณต้องการทราบข้อมูลเชิงลึกเกี่ยวกับการสั่งซื้อคุณควรอ่านเกี่ยวกับการสั่งซื้ออัลกอริธึม
helios

ขอบคุณฉันจะดูสิ่งเหล่านั้นฉันไม่รู้อะไรเลยเกี่ยวกับการเรียงลำดับ

พบโซลูชัน Java 1.8 ที่มีประโยชน์มากมายในเธรดนี้: stackoverflow.com/questions/36361156/…
lradacher

คำตอบ:


418

คุณสามารถทำให้วัตถุของคุณเปรียบได้:

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 นั้นไม่เป็นโมฆะในขณะทำการเปรียบเทียบ ก็ควรที่จะจัดการกับค่าว่างเช่นกันเพื่อหลีกเลี่ยง NullPointerExceptions:

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
เหตุผลสองประการคือความเรียบง่ายและล้มเหลว คุณต้องการให้รหัสนั้นง่ายที่สุดเท่าที่จะเป็นไปได้และถ้าคุณแน่ใจว่าทรัพย์สินของคุณไม่ควรเป็นโมฆะคุณอาจต้องการให้โค้ดของคุณล้มเหลวโดยเร็วที่สุดหากคุณพบว่ามีค่าว่างแทนที่จะส่งผ่านข้อมูลที่ไม่ถูกต้อง ตำแหน่งที่แนะนำข้อมูลที่ไม่ถูกต้อง
Domchi

3
ถ้า o1 หรือ o2 เป็นโมฆะให้ส่งคืน 0 // บรรทัดนี้อาจทำให้เกิดข้อผิดพลาดเมื่อส่งคืน 0 หมายความว่าพวกเขาเท่ากัน
tanyehzheng

@tanyehzheng ถูกต้องมันเป็นความเข้าใจผิด แต่โปรดทราบว่ามีความแตกต่างระหว่าง. compareTo () ซึ่งใช้สำหรับการเรียงลำดับและ. equals () มันขึ้นอยู่กับว่าคุณต้องการจัดการค่า null ของคุณอย่างไรในระหว่างการเรียงลำดับ
Domchi

1
คุณควรตรวจสอบค่าว่างของแต่ละวันแยกจากกันและจัดเรียงตามที่ต้องการ นั่นคือถ้าหนึ่งวันเป็นโมฆะและหนึ่งไม่เป็นโมฆะส่งคืน 1 หรือ -1 หากไม่มีการทำเช่นนั้นค่า null จะไม่ถูกจัดเรียงและคงอยู่ไม่ว่าจะเกิดขึ้นในรายการก่อนการจัดเรียงหรือไม่
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 เป็นประเภทที่เปรียบเทียบได้ (อันที่ใช้อินเทอร์เฟซที่เปรียบเทียบได้) (เช่น Date, Integer หรือ String) คุณสามารถละเว้นตัวเปรียบเทียบและการเรียงลำดับแบบธรรมชาติจะถูกใช้


1
และนี่จะคืนค่า myList เมื่อเสร็จสิ้นหรืออย่างนั้นหรือ

มันปรับเปลี่ยนรายการของฉัน ดังนั้นจึงจัดเรียงเมื่อเสร็จสิ้น
helios


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

คำตอบที่ดีที่สุดจาก IMHO จาก Tunaki โดยใช้ Java 8 แลมบ์ดา


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;
    }
});

จะทำอย่างไรถ้าฉันต้องการสั่งซื้อตามเวลาปัจจุบันของระบบ
User3

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

คำตอบทั้งหมดที่นี่ฉันพบว่าไม่ซับซ้อนโดยไม่จำเป็นสำหรับปัญหาง่ายๆ (อย่างน้อยก็สำหรับนักพัฒนาจาวาที่มีประสบการณ์ซึ่งฉันไม่ได้เป็น) ฉันมีปัญหาที่คล้ายกันและมีโอกาสแก้ปัญหานี้ (และอื่น ๆ ) และแม้ว่าพวกเขาจะให้ตัวชี้สำหรับผู้เริ่มต้นที่ฉันพบตามที่ระบุไว้ข้างต้น โซลูชันของฉันขึ้นอยู่กับว่าวันที่วัตถุของคุณอยู่ในกรณีนี้วันที่เป็นองค์ประกอบแรกของ 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 คือข้อเสียเปรียบต่อผู้พัฒนาจาวามือใหม่ของฉัน (หลังจากนั้น) ที่ไม่มีประสบการณ์ การรวม typecasting ในคำตอบของฉันคือ clincher (อย่างน้อยก็ในใจของฉัน) มีอะไรเหลืออยู่ที่คุณถอนการอ้างสิทธิ์ที่คำตอบของฉันถูกกว่าคนอื่น ๆ ? ฉันคิดว่าการปล่อยไอน้ำออกไป .. ทั้งหมดได้รับการอภัย!
Nepaluz

o.getDateTime () ไม่เกี่ยวกับการพิมพ์ แต่เป็นเรื่องเกี่ยวกับคำอธิบายของ OP ของDateTimeวัตถุที่บรรจุอยู่ในวัตถุอื่น หากเป็นเพียงวัตถุDateหรือDateTimeวัตถุที่Comparableไม่จำเป็นต้องมีComparatorในครั้งแรก
amotzg

ไม่ได้หมายความว่าคำตอบของคุณถูกต้องน้อยกว่าหรือดีกว่าน้อยกว่า ฉันแค่หาข้อมูลเพื่อช่วยให้ฉันเข้าใจมันมากขึ้น ฉันขอโทษถ้ามันดูเหมือนจะเป็นอย่างอื่น
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 เมื่อใดก็ได้ในอาเรย์และมันจะเรียงลำดับอาเรย์ของฉันให้ฉัน timestamp ล่าสุดในตำแหน่ง 0 (ด้านบนของรายการ) และเวลาที่เร็วที่สุดในตอนท้ายของรายการ โพสต์ใหม่จะถูกนำไปด้านบนโดยทั่วไป

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

นี่อาจช่วยให้ใครบางคนออกมาซึ่งเป็นสาเหตุที่ฉันโพสต์ไว้ คำนึงถึงคำสั่ง return ภายในฟังก์ชั่น compar () ผลลัพธ์มี 3 ประเภท ส่งกลับ 0 ถ้าพวกเขามีค่าเท่ากันกลับ> 0 ถ้าวันแรกอยู่ก่อนวันที่สองและกลับมา <0 ถ้าวันแรกคือหลังจากวันที่สอง หากคุณต้องการให้รายการของคุณกลับรายการเพียงแค่สลับคำสั่งส่งคืนทั้งสองนั้น! Simple =]


ฉันต้องการที่จะเพิ่มความคิดเห็นเกี่ยวกับเรื่องนี้ แน่นอนว่ามี "NullPointerExceptions" เมื่อจัดการรายการอาร์เรย์ (ให้คำสั่ง return 0) ดังนั้นคุณจะต้องจัดการกับมันเนื่องจากแต่ละกรณีจะแตกต่างกัน ตัวอย่างเช่นรายการที่มีวัตถุ 0 รายการจะสร้าง NullPointerException หรือรายการที่มี 1 วัตถุ!
แบรนดอน

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 วันที่และเวลา APIDateTimeFormatterและ
Ole VV

0

คลาส Date ใช้อินเทอร์เฟซเครื่องมือเปรียบเทียบ สมมติว่าคุณมีชั้นเรียนด้านล่าง:

public class A {

    private Date dateTime;

    public Date getDateTime() {
        return dateTime;
    }

    .... other variables

}

และสมมติว่าคุณมีรายการของวัตถุ A List<A> aListคุณสามารถเรียงลำดับด้วย API สตรีมของ Java 8 (ตัวอย่างด้านล่าง):

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.