我是Java的初学者。请建议可以/应该使用哪些集合来维护Java中的排序列表。我尝试了Map
和Set
,但他们并不是我想要的。
答案 0 :(得分:182)
这很晚,但是JDK中有一个类只是为了有一个排序列表。它被命名(与其他Sorted*
接口有点不正常)“java.util.PriorityQueue
”。它可以对Comparable<?>
进行排序,也可以使用Comparator
。
使用List
排序的Collections.sort(...)
的差异在于,通过使用堆数据结构,它将始终保持部分顺序,具有O(log(n))插入性能,而在排序的ArrayList
中插入将是O(n)(即,使用二进制搜索和移动)。
但是,与List
不同,PriorityQueue
不支持索引访问(get(5)
),访问堆中项目的唯一方法是将其取出,一次(因此名称为PriorityQueue
)。
答案 1 :(得分:53)
TreeMap和TreeSet将按排序顺序对内容进行迭代。或者您可以使用ArrayList并使用Collections.sort()对其进行排序。所有这些类都在java.util
中答案 2 :(得分:32)
如果您想维护排序列表,您将经常修改(即除了排序之外,还允许重复且其元素可以有效的结构由index引用,然后使用ArrayList,但是当您需要插入元素时,请始终使用 Collections.binarySearch()来确定添加给定元素的索引。后一种方法告诉您需要插入的索引,以使列表保持排序顺序。
答案 3 :(得分:31)
使用Google Guava的TreeMultiset课程。 Guava有一个壮观的集合API。
提供维护排序顺序的List实现的一个问题是add()
方法的JavaDocs中的承诺。
答案 4 :(得分:12)
答案 5 :(得分:12)
有几个选择。如果你不想要重复,我建议使用TreeSet,你插入的对象是可比较的。
您还可以使用Collections类的静态方法执行此操作。
有关详细信息,请参阅Collections#sort(java.util.List)和TreeSet。
答案 6 :(得分:9)
如果您只想对列表进行排序,请使用任何类型的List并使用Collections.sort()。如果要确保列表中的元素是唯一的并且始终排序,请使用SortedSet。
答案 7 :(得分:5)
我所做的是实现具有委托所有方法的内部实例的List。
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);
}
如果要避免插入,还可以在“add”和“set”方法上抛出和不支持的操作异常。
public boolean add(Contact object) {
throw new UnsupportedOperationException("Use putOrdered instead");
}
...而且你必须小心ListIterator方法,因为他们可以修改你的内部列表。在这种情况下,您可以返回内部列表的副本或再次抛出异常。
public ListIterator<Contact> listIterator() {
return (new ArrayList<Contact>(list)).listIterator();
}
答案 8 :(得分:4)
如果您使用的是Java 8的先前版本,可以尝试使用 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());
}
});
按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()));
答案 9 :(得分:4)
实现您想要的排序列表的最有效方法是实现可索引的跳过列表,如下所示:Wikipedia: Indexable skiplist。 它允许在O(log(n))中插入/删除,并允许同时具有索引访问。它也会允许重复。
跳过清单非常有趣,我想说,它被低估了数据结构。 遗憾的是,Java库中没有索引跳过列表实现,但您可以使用其中一个开源实现或自己实现。有常规的跳过列表实现,如ConcurrentSkipListSet和ConcurrentSkipListMap
答案 10 :(得分:4)
TreeSet不起作用,因为它们不允许重复,而且它们不提供在特定位置获取元素的方法。 PriorityQueue不起作用,因为它不允许在特定位置获取元素,这是列表的基本要求。 我认为您需要实现自己的算法来维护带有O(logn)插入时间的Java中的排序列表,除非您不需要重复项。 也许解决方案可能是使用TreeMap,其中键是覆盖equals方法的项的子类,以便允许重复。
答案 11 :(得分:2)
PriorityQueue的问题在于它由一个简单的数组支持,并且按顺序获取元素的逻辑由“queue [2 * n + 1]和queue [2 *(n + 1)]完成“东西。如果你只是从头部拉出来它会很有效,但是如果你试图在某个时候调用.toArray,它会变得无用。
我通过使用com.google.common.collect.TreeMultimap解决了这个问题,但是我提供了一个自定义的Comparator,它包含在Ordering中,永远不会返回0.
离。 for Double:
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()时,我按顺序获取值,并且还有重复项。
答案 12 :(得分:1)
你想要的是二叉搜索树。它维护排序顺序,同时提供搜索,删除和插入的对数访问(除非你有一个退化树 - 然后它是线性的)。它很容易实现,甚至可以使它实现List接口,但是索引访问变得复杂。
第二种方法是使用ArrayList,然后使用冒泡排序实现。由于您一次插入或删除一个元素,因此插入和删除的访问时间是线性的。搜索是对数和索引访问常量(LinkedList的时间可以不同)。您需要的唯一代码是5个,可能是6行冒泡排序。
答案 13 :(得分:1)
您可以使用Arraylist和Treemap,正如您所说,您想要重复的值,然后您不能使用TreeSet,尽管它也已经排序,但您必须定义比较器。
答案 14 :(得分:1)
对于Set,您可以使用TreeSet。 TreeSet根据自然顺序或传递给该特定对象的Comparable的任何排序顺序对元素进行排序。 对于地图,请使用TreeMap。 TreeMap提供了对键的排序。为了将对象添加为TreeMap的键,该类应实现可比较的接口,从而强制实现包含排序顺序定义的compare to()方法。 http://techmastertutorial.in/java-collection-impl.html
答案 15 :(得分:0)
使用sort()方法对列表进行排序,如下所示:
List list = new ArrayList();
//add elements to the list
Comparator comparator = new SomeComparator();
Collections.sort(list, comparator);
供参考,请参阅链接: https://www.quora.com/How-does-Facebook-know-what-I-looked-at-on-Amazon
答案 16 :(得分:0)
使用TreeSet
以排序顺序提供元素。或使用Collection.sort()
与Comparator()
进行外部排序。
答案 17 :(得分:0)
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);
}
答案 18 :(得分:0)
使用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);
}
}
答案 19 :(得分:0)
根据用户定义的标准对ArrayList进行排序。
模型类
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