ฉันเป็นผู้เริ่มต้นใน Java กรุณาแนะนำคอลเลกชันที่สามารถ / ควรใช้สำหรับการรักษารายการเรียงลำดับใน Java ฉันได้พยายามMap
และSet
แต่พวกเขาก็ไม่ได้สิ่งที่ผมกำลังมองหา
ฉันเป็นผู้เริ่มต้นใน Java กรุณาแนะนำคอลเลกชันที่สามารถ / ควรใช้สำหรับการรักษารายการเรียงลำดับใน Java ฉันได้พยายามMap
และSet
แต่พวกเขาก็ไม่ได้สิ่งที่ผมกำลังมองหา
คำตอบ:
สิ่งนี้มาช้ามาก แต่มีคลาสใน JDK เพียงเพื่อจุดประสงค์ในการจัดเรียงรายการ มันถูกตั้งชื่อ (ค่อนข้างผิดปกติกับSorted*
อินเทอร์เฟซอื่น) " java.util.PriorityQueue
" มันสามารถจัดเรียงอย่างใดอย่างหนึ่งหรือใช้Comparable<?>
Comparator
ความแตกต่างกับการList
เรียงลำดับการใช้Collections.sort(...)
คือสิ่งนี้จะรักษาลำดับบางส่วนตลอดเวลาด้วยประสิทธิภาพการแทรก O (log (n)) โดยใช้โครงสร้างข้อมูล heap ในขณะที่การแทรกในการเรียงArrayList
จะเป็น O (n) (เช่น ใช้การค้นหาและย้ายแบบไบนารี่)
อย่างไรก็ตามแตกต่างจาก a List
, PriorityQueue
ไม่รองรับการเข้าถึงที่จัดทำดัชนี ( get(5)
), วิธีเดียวที่จะเข้าถึงไอเท็มในฮีปคือการนำพวกเขาออกทีละครั้ง (เช่นชื่อPriorityQueue
)
TreeMap และ TreeSet จะให้คุณทำซ้ำเนื้อหาตามลำดับ หรือคุณสามารถใช้ ArrayList และใช้ Collections.sort () เพื่อจัดเรียง คลาสทั้งหมดเหล่านั้นอยู่ใน java.util
หากคุณต้องการรักษารายการที่เรียงซึ่งคุณมักจะแก้ไข (เช่นโครงสร้างซึ่งนอกเหนือจากการเรียงลำดับอนุญาตให้ทำซ้ำและองค์ประกอบที่สามารถอ้างอิงได้อย่างมีประสิทธิภาพโดยดัชนี) จากนั้นใช้ ArrayList แต่เมื่อคุณต้องการแทรกองค์ประกอบ ใช้Collections.binarySearch () เพื่อกำหนดดัชนีที่คุณเพิ่มองค์ประกอบที่กำหนด เมธอดหลังจะบอกดัชนีที่คุณต้องการแทรกที่จะเก็บรายการของคุณตามลำดับ
ใช้คลาสTreeMultisetของ Google Guava Guavaมี API คอลเล็กชันที่งดงาม
ปัญหาหนึ่งที่เกิดขึ้นกับการจัดให้มีการอิมพลีเมนต์ List ที่รักษาลำดับการเรียงไว้คือสัญญาที่ทำไว้ใน JavaDocs ของadd()
เมธอด
List
เพิ่มเข้ามาเสมอในตอนท้าย
คุณต้องการSortedSetการใช้งานคือTreeSet
มีตัวเลือกน้อย ฉันขอแนะนำ TreeSet หากคุณไม่ต้องการให้มีรายการที่ซ้ำกันและวัตถุที่คุณใส่มีการเปรียบเทียบ
คุณยังสามารถใช้วิธีการคงที่ของคลาส Collections เพื่อทำสิ่งนี้
ดูที่Collections # sort (java.util.List)และTreeSetสำหรับข้อมูลเพิ่มเติม
หากคุณเพียงแค่ต้องการที่จะเรียงลำดับรายการให้ใช้ชนิดของใด ๆรายการและใช้Collections.sort () หากคุณต้องการให้แน่ใจว่าองค์ประกอบในรายการที่เป็นเอกลักษณ์และเรียงเสมอใช้SortedSet
สิ่งที่ฉันได้ทำคือการใช้รายการที่มีอินสแตนซ์ภายในที่มีวิธีการทั้งหมดที่ได้รับมอบหมาย
public class ContactList implements List<Contact>, Serializable {
private static final long serialVersionUID = -1862666454644475565L;
private final List<Contact> list;
public ContactList() {
super();
this.list = new ArrayList<Contact>();
}
public ContactList(List<Contact> list) {
super();
//copy and order list
List<Contact>aux= new ArrayList(list);
Collections.sort(aux);
this.list = aux;
}
public void clear() {
list.clear();
}
public boolean contains(Object object) {
return list.contains(object);
}
หลังจากฉันฉันได้ใช้วิธีการใหม่ "putOrdered" ซึ่งแทรกอยู่ในตำแหน่งที่เหมาะสมหากองค์ประกอบไม่ได้อยู่หรือแทนที่ในกรณีที่มันมีอยู่
public void putOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
list.add(index, contact);
}else{
list.set(index, contact);
}
}
หากคุณต้องการอนุญาตให้องค์ประกอบที่ซ้ำกันเพียงแค่ใช้ addOrdered แทน (หรือทั้งสองอย่าง)
public void addOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
}
list.add(index, contact);
}
หากคุณต้องการหลีกเลี่ยงการแทรกคุณสามารถโยนและไม่สนับสนุนข้อยกเว้นการดำเนินการในวิธีการ "เพิ่ม" และ "ตั้ง"
public boolean add(Contact object) {
throw new UnsupportedOperationException("Use putOrdered instead");
}
... และคุณต้องระวังด้วยวิธี ListIterator เพราะพวกเขาสามารถแก้ไขรายการภายในของคุณ ในกรณีนี้คุณสามารถส่งคืนสำเนาของรายการภายในหรือโยนข้อยกเว้นอีกครั้ง
public ListIterator<Contact> listIterator() {
return (new ArrayList<Contact>(list)).listIterator();
}
List
สัญญา Collection
บางทีมันอาจจะดีกว่าที่จะดำเนินการเท่านั้น และหากContactList
มีการเรียงลำดับก็contains()
สามารถนำไปใช้งานได้binarySearch
เช่นกันเพื่อให้มีประสิทธิภาพมากขึ้น
วิธีที่มีประสิทธิภาพมากที่สุดในการใช้รายการที่เรียงลำดับตามที่คุณต้องการคือการใช้ skiplist ที่จัดทำดัชนีได้เช่นเดียวกับที่นี่: Wikipedia: skiplist ที่จัดทำดัชนีได้ มันจะช่วยให้มีการแทรก / ลบใน O (log (n)) และจะอนุญาตให้มีการเข้าถึงดัชนีในเวลาเดียวกัน และมันก็จะอนุญาตให้ซ้ำกัน
Skiplist นั้นค่อนข้างน่าสนใจและผมอยากบอกว่าโครงสร้างข้อมูลที่มีการประเมินต่ำเกินไป น่าเสียดายที่ไม่มีการใช้งาน skiplist ที่จัดทำดัชนีไว้ในไลบรารีฐาน Java แต่คุณสามารถใช้การใช้งานโอเพนซอร์ซหรือใช้งานด้วยตัวคุณเอง มีการใช้งาน Skiplist ปกติเช่นConcurrentSkipListSetและConcurrentSkipListMap
TreeSet จะไม่ทำงานเพราะไม่อนุญาตให้มีการทำซ้ำและจะไม่ให้วิธีการดึงข้อมูลองค์ประกอบที่ตำแหน่งที่เฉพาะเจาะจง PriorityQueue จะไม่ทำงานเพราะไม่อนุญาตให้เรียกองค์ประกอบที่ตำแหน่งเฉพาะซึ่งเป็นข้อกำหนดขั้นพื้นฐานสำหรับรายการ ฉันคิดว่าคุณต้องใช้อัลกอริทึมของคุณเองเพื่อรักษารายการเรียงลำดับใน Java ที่มีเวลาแทรก O (logn) เว้นแต่ว่าคุณไม่ต้องการทำซ้ำ บางทีโซลูชันอาจใช้ TreeMap โดยที่คีย์เป็นคลาสย่อยของรายการที่แทนที่เมธอด equals เพื่ออนุญาตการทำซ้ำ
คุณสามารถลองแก้ปัญหาเหล่านี้ด้วยLambdaJหากคุณใช้รุ่นก่อนหน้านี้กับ java 8 คุณสามารถค้นหาได้ที่นี่: 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());
}
});
จัดเรียงด้วย LambdaJ
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
แน่นอนว่าการมีความงามแบบนี้ส่งผลกระทบต่อการแสดง (โดยเฉลี่ย 2 ครั้ง) แต่คุณสามารถหารหัสที่อ่านได้มากขึ้นหรือไม่?
Collections.sort(persons, (p1, p2) -> p1.getAge().compareTo(p2.getAge()));
//or
persons.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));
-(p1.getAge().compareTo(p2.getAge()))
ปัญหาของ PriorityQueue คือมันถูกสำรองข้อมูลโดยอาเรย์อย่างง่ายและตรรกะที่ได้รับองค์ประกอบตามลำดับนั้นทำได้โดย "คิว [2 * n + 1] และคิว [2 * (n + 1)]" thingie มันใช้งานได้ดีถ้าคุณดึงออกจากหัว แต่ทำให้มันไร้ประโยชน์ถ้าคุณพยายามโทรหา. toArray ในบางจุด
ฉันแก้ไขปัญหานี้โดยใช้ com.google.common.collect.TreeMultimap แต่ฉันให้ตัวเปรียบเทียบที่กำหนดเองสำหรับค่าในการสั่งซื้อซึ่งจะไม่ส่งคืนค่า 0
อดีต สำหรับคู่:
private static final Ordering<Double> NoEqualOrder = Ordering.from(new Comparator<Double>() {
@Override
public int compare(Double d1, Double d2)
{
if (d1 < d2) {
return -1;
}
else {
return 1;
}
}
});
วิธีนี้ฉันจะได้รับค่าตามลำดับเมื่อฉันโทร. toArray () และยังมีซ้ำ
สิ่งที่คุณต้องการคือแผนภูมิการค้นหาแบบไบนารี มันรักษาลำดับการจัดเรียงในขณะที่ให้การเข้าถึงลอการิทึมสำหรับการค้นหาการลบและการแทรก (เว้นแต่ว่าคุณจะมีต้นไม้ที่เสื่อมโทรม มันค่อนข้างง่ายที่จะติดตั้งและคุณสามารถทำให้มันใช้ List Interface ได้ แต่การเข้าถึงดัชนีนั้นซับซ้อน
วิธีที่สองคือการมี ArrayList และการปรับใช้การเรียงลำดับฟอง เนื่องจากคุณกำลังแทรกหรือลบองค์ประกอบหนึ่งครั้งเวลาเข้าถึงสำหรับการแทรกและการลบจึงเป็นแบบเชิงเส้น การค้นหาเป็นลอการิทึมและค่าคงที่การเข้าถึงดัชนี (ครั้งสามารถแตกต่างกันสำหรับ LinkedList) รหัสเดียวที่คุณต้องการคือ 5 อาจจะเรียงลำดับฟองได้ 6 บรรทัด
คุณสามารถใช้ Arraylist และ Treemap อย่างที่คุณบอกว่าคุณต้องการค่าซ้ำ ๆ เช่นกันจากนั้นคุณไม่สามารถใช้ TreeSet ได้แม้ว่ามันจะถูกจัดเรียงเช่นกัน แต่คุณต้องกำหนดตัวเปรียบเทียบ
สำหรับ Set คุณสามารถใช้ TreeSet ชุดคำสั่ง TreeSet เป็นองค์ประกอบตามลำดับธรรมชาติหรือลำดับการเรียงลำดับใด ๆ ที่ส่งผ่านไปเปรียบเทียบได้สำหรับวัตถุนั้น ๆ สำหรับแผนที่ใช้ TreeMap TreeMap จัดให้มีการเรียงลำดับมากกว่ากุญแจ ในการเพิ่มวัตถุเป็นกุญแจสำคัญใน TreeMap นั้นคลาสนั้นควรใช้อินเตอร์เฟสที่เทียบเคียงกันซึ่งจะบังคับให้ใช้วิธีการเปรียบเทียบกับ () ซึ่งมีคำจำกัดความของคำสั่งการเรียงลำดับ http://techmastertutorial.in/java-collection-impl.html
ใช้วิธีการเรียง () เพื่อจัดเรียงรายการดังต่อไปนี้:
List list = new ArrayList();
//add elements to the list
Comparator comparator = new SomeComparator();
Collections.sort(list, comparator);
สำหรับการอ้างอิงดูลิงค์: http://tutorials.jenkov.com/java-collections/sorting.html
ใช้TreeSet
ที่ให้องค์ประกอบในการเรียงลำดับ หรือใช้สำหรับการเรียงลำดับภายนอกที่มีCollection.sort()
Comparator()
import java.util.TreeSet;
public class Ass3 {
TreeSet<String>str=new TreeSet<String>();
str.add("dog");
str.add("doonkey");
str.add("rat");
str.add("rabbit");
str.add("elephant");
System.out.println(str);
}
ด้วย Java 8 Comparator ถ้าเราต้องการเรียงลำดับรายการนี่คือ 10 เมืองที่มีประชากรมากที่สุดในโลกและเราต้องการเรียงลำดับตามชื่อตามที่รายงานโดย Time โอซาก้าประเทศญี่ปุ่น ... เม็กซิโกซิตี้เม็กซิโก ... ปักกิ่ง, จีน ... เซาเปาโล, บราซิล ... มุมไบประเทศอินเดีย ... เซียงไฮ้ประเทศจีน. ... เดลี, อินเดีย ... โตเกียว, ญี่ปุ่น.
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class SortCityList {
/*
* Here are the 10 most populated cities in the world and we want to sort it by
* name, as reported by Time. Osaka, Japan. ... Mexico City, Mexico. ...
* Beijing, China. ... São Paulo, Brazil. ... Mumbai, India. ... Shanghai,
* China. ... Delhi, India. ... Tokyo, Japan.
*/
public static void main(String[] args) {
List<String> cities = Arrays.asList("Osaka", "Mexico City", "São Paulo", "Mumbai", "Shanghai", "Delhi",
"Tokyo");
System.out.println("Before Sorting List is:-");
System.out.println(cities);
System.out.println("--------------------------------");
System.out.println("After Use of List sort(String.CASE_INSENSITIVE_ORDER) & Sorting List is:-");
cities.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println(cities);
System.out.println("--------------------------------");
System.out.println("After Use of List sort(Comparator.naturalOrder()) & Sorting List is:-");
cities.sort(Comparator.naturalOrder());
System.out.println(cities);
}
}
การเรียงลำดับ ArrayList ตามเกณฑ์ที่ผู้ใช้กำหนด
Class Model
class Student
{
int rollno;
String name, address;
public Student(int rollno, String name, String address)
{
this.rollno = rollno;
this.name = name;
this.address = address;
}
public String toString()
{
return this.rollno + " " + this.name + " " + this.address;
}
}
คลาสการเรียงลำดับ
class Sortbyroll implements Comparator<Student>
{
public int compare(Student a, Student b)
{
return a.rollno - b.rollno;
}
}
ชั้นเรียนหลัก
class Main
{
public static void main (String[] args)
{
ArrayList<Student> ar = new ArrayList<Student>();
ar.add(new Student(111, "bbbb", "london"));
ar.add(new Student(131, "aaaa", "nyc"));
ar.add(new Student(121, "cccc", "jaipur"));
System.out.println("Unsorted");
for (int i=0; i<ar.size(); i++)
System.out.println(ar.get(i));
Collections.sort(ar, new Sortbyroll());
System.out.println("\nSorted by rollno");
for (int i=0; i<ar.size(); i++)
System.out.println(ar.get(i));
}
}
เอาท์พุต
Unsorted
111 bbbb london
131 aaaa nyc
121 cccc jaipur
Sorted by rollno
111 bbbb london
121 cccc jaipur
131 aaaa nyc