Điều này đã gây phiền toái cho tôi trong một dự án gần đây và Google phoo của tôi không làm tôi tìm câu trả lời phù hợp.Bộ sưu tập sử dụng ListIterator và là một danh sách duy nhất
Có bộ sưu tập nào có quyền truy cập vào ListIterator
nhưng cũng chỉ cho phép các giá trị duy nhất bên trong bộ sưu tập không?
Lý do cho điều này, tôi có một bộ sưu tập các mục trong bộ sưu tập này sẽ chỉ bao giờ là một trong mỗi phần tử. Tôi cũng muốn có thể duyệt bộ sưu tập này theo cả hai hướng. và tôi muốn nó thể là sắp xếp hoặc cho phép tôi để sắp xếp nó bằng cách sử Collections.Sort();
tôi đã không tìm thấy bất cứ điều gì phù hợp và phải viết lớp của riêng tôi bằng cách sử dụng đoạn mã sau:
public class UniqueArrayList<E> extends ArrayList<E> {
@Override
public boolean add(E element){
if (this.contains(element))
return false;
else
return super.add(element);
}
@Override
public void add(int index, E element){
if (this.contains(element))
return;
else
super.add(index, element);
}
@Override
public boolean addAll(Collection<? extends E> c){
if (new HashSet<E>(c).size() < c.size())
return false;
for(E element : c){
if (this.contains(c))
return false;
}
return super.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
if (new HashSet<E>(c).size() < c.size())
return false;
for(E element : c){
if (this.contains(c))
return false;
}
return super.addAll(index, c);
}
@Override
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > this.size())
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
@Override
public ListIterator<E> listIterator() {
return new ListItr(0);
}
@Override
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size())
throw new NoSuchElementException();
Object[] elementData = UniqueArrayList.this.toArray();
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
UniqueArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = UniqueArrayList.this.toArray();
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
//Need to allow this for the collections sort to work!
//if (!UniqueArrayList.this.contains(e))
UniqueArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
UniqueArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
}
Tuy nhiên điều này là xa từ hoàn hảo, vì tôi không thể ghi đè lên ListIterator.set();
vì Collections.sort();
sử dụng nó để di chuyển các mục trong danh sách. Nếu tôi cố gắng ngăn không cho các mục không độc đáo được thêm vào danh sách ở đây, sắp xếp không bao giờ xảy ra.
Vì vậy, có ai có phương pháp tốt hơn hoặc biết về một bộ sưu tập khác tuân theo các quy tắc mà tôi muốn không? Hay tôi chỉ cần sống với vấn đề khá khó chịu này?
[Chỉnh sửa] Đây là Collections.sort();
phương pháp:
public static <T extends Comparable<? super T>> void sort(List<T> list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
Lý do họ đưa ra cho việc này là:
thi này bãi danh mục quy định vào một mảng, sắp xếp các mảng và lặp lại trên danh sách đặt lại từng phần tử từ vị trí tương ứng trong mảng. Điều này tránh được các hiệu suất n nhật ký (n) sẽ xuất phát từ việc cố gắng sắp xếp danh sách được liên kết tại chỗ.
Phiên bản Java bạn đang sử dụng? – Kayaman
Bạn đã đưa ra ý tưởng rằng 'Collections.sort();' sử dụng 'ListIterator.set();'? – Kayaman
Java 1.7 và kiểm tra văn bản cập nhật của tôi trong các câu hỏi liên quan đến phương pháp sắp xếp – Draken