Objective-C에 익숙한 사람이 있으면 SetNSOrderedSet
역할을 하는 컬렉션이 있으며 해당 항목은 Array 의 항목으로 액세스 할 수 있습니다 .
Java에 이와 같은 것이 있습니까?
라는 컬렉션이 있다고 들었지만 LinkedHashMap
세트에 대해 이와 비슷한 것을 찾지 못했습니다.
Objective-C에 익숙한 사람이 있으면 SetNSOrderedSet
역할을 하는 컬렉션이 있으며 해당 항목은 Array 의 항목으로 액세스 할 수 있습니다 .
Java에 이와 같은 것이 있습니까?
라는 컬렉션이 있다고 들었지만 LinkedHashMap
세트에 대해 이와 비슷한 것을 찾지 못했습니다.
답변:
LinkedHashSet 클래스 살펴보기
예측 가능한 반복 순서 와 함께 Set 인터페이스의 해시 테이블 및 연결 목록 구현 . 이 구현은 모든 항목을 통해 실행되는 이중 연결 목록을 유지한다는 점에서 HashSet과 다릅니다. 이 연결 목록은 요소가 집합에 삽입 된 순서 인 반복 순서를 정의합니다 (insertion-order) . 요소가 세트에 다시 삽입되는 경우 게재 순서는 영향을받지 않습니다 . (s.contains (e)가 호출 직전에 true를 반환 할 때 s.add (e)가 호출되면 요소 e가 집합 s에 다시 삽입됩니다.)
LinkedHashMap
보이지만 어떻게 든 찾지 못했습니다.
LinkedHashSet
요소가 어떤 인덱스에 있는지 알아낼 수있는 기능이 없습니다 .
모든 Set에는 iterator ()가 있습니다. 일반적인 HashSet의 반복자는 매우 무작위 적이며 TreeSet은 정렬 순서로 수행하고 LinkedHashSet 반복자는 삽입 순서로 반복합니다.
그러나 LinkedHashSet의 요소를 바꿀 수는 없습니다. 하나를 제거하고 다른 요소를 추가 할 수 있지만 새 요소는 원본 위치에 있지 않습니다. LinkedHashMap에서 기존 키의 값을 바꿀 수 있으며 값은 원래 순서대로 유지됩니다.
또한 특정 위치에 삽입 할 수 없습니다.
중복 삽입을 피하기 위해 명시 적 검사와 함께 ArrayList를 사용하는 것이 좋습니다.
LinkedHashSet
해야하는 것은 솔기입니다 . 답장 해 주셔서 감사합니다
Java 표준 API 문서를 살펴보십시오 . 바로 옆에 LinkedHashMap
하는있다 LinkedHashSet
. 그러나 그 순서는 요소의 자연스러운 순서가 아니라 삽입 순서입니다. 그리고 무작위 액세스를 수행하지 않고 해당 순서로만 반복 할 수 있습니다 (반복 단계 계산 제외).
및에 SortedSet
의해 구현 된 인터페이스도 있습니다 . 둘 다 요소 또는 a 의 자연스러운 순서 로 반복을 허용 하지만 임의 액세스 또는 삽입 순서는 허용하지 않습니다.TreeSet
ConcurrentSkipListSet
Comparator
인덱스로 효율적으로 액세스 할 수 있고 설정된 기준을 효율적으로 구현할 수있는 데이터 구조의 경우 건너 뛰기 목록이 필요 하지만 Java Standard API에는 해당 기능이 구현되어 있지 않지만 쉽게 찾을 수 있습니다. 인터넷에서.
ConcurrentSkipListMap
및 ConcurrentSkipListSet
. 둘 다 자연 순서 또는 비교기를 기반으로 정렬을 유지합니다. 나는 그들이 당신이 논의하는 무작위 액세스 또는 진입 순서를 제공하는지 이해하지 못합니다.
java.util.TreeSet
그 구현을 사용해보십시오 SortedSet
.
문서를 인용하려면 :
"요소는 자연 순서를 사용하거나 사용되는 생성자에 따라 설정된 생성 시간에 제공된 비교기를 사용하여 정렬됩니다."
추가, 제거 및 포함에는 시간 비용 log (n)가 있습니다.
집합의 내용에 배열로 액세스하려면 다음을 수행하여 변환 할 수 있습니다.
YourType[] array = someSet.toArray(new YourType[yourSet.size()]);
이 배열은 TreeSet과 동일한 기준 (자연 또는 비교기)으로 정렬되며, 많은 경우 Arrays.sort ()를 수행하는 대신 이점이 있습니다.
c
하고 요소를 a
내가 같은 순서로 싶어 I으로 반복 모음 이상으로, : c
, a
등
생략 목록의 저렴한 구현에 대해 이야기하고 있다면 빅 O의 관점에서이 작업의 비용이 얼마인지 궁금합니다.
YourType [] array = someSet.toArray (new YourType [yourSet.size ()]);
내 말은 항상 전체 배열 생성에 갇혀 있으므로 O (n)입니다.
java.util.Arrays#copyOf
size()
기본 집합 의 방법에 따라 다릅니다 . 반복은 보통 O(n)
크기는 일반적으로, O(1)
를 제외하고 ConcurrentSkipListSet
는 어디 O(n)
.
indexed-tree-map 프로젝트 의 IndexedTreeSet 은이 기능을 제공합니다 (색인 별 목록과 유사한 액세스로 정렬 / 정렬 된 집합).
또한 같은 양방향지도의 일부 유틸리티 아웃 얻을 수 있습니다 BiMap
에서 구글 구아바
를 사용하면 BiMap
Integer (임의 인덱스 액세스 용)를 다른 객체 유형에 매우 효율적으로 매핑 할 수 있습니다. BiMap
s는 일대일이므로 주어진 정수에는 최대 하나의 요소가 연결되고 모든 요소에는 하나의 연결된 정수가 있습니다. 두 개의 HashTable
인스턴스에 의해 영리하게 뒷받침 되므로 거의 두 배의 메모리를 사용하지만 List
처리 하는 한 커스텀보다 훨씬 효율적입니다. contains()
(이미 존재하는지 확인하기 위해 항목이 추가 될 때 호출 됨)이 일정 시간이기 때문입니다. 평행 쉬운 작업처럼 HashSet
의 반면 List
의 구현이 훨씬 느리다.
비슷한 문제가있었습니다. 나는 주문한 세트가 필요하지 않았지만 빠른 indexOf
/ contains
. 거기에서 아무것도 찾지 못했기 때문에 직접 구현했습니다. 다음은 코드입니다. 모든 대량 목록 작업이 버전 만큼 빠르지는 않지만 Set
및을 모두 구현합니다 .List
ArrayList
면책 조항 : 테스트되지 않음
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.Collection;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import static java.util.Objects.requireNonNull;
/**
* An ArrayList that keeps an index of its content so that contains()/indexOf() are fast. Duplicate entries are
* ignored as most other java Set's do.
*/
public class IndexedArraySet<E> extends ArrayList<E> implements Set<E> {
public IndexedArraySet() { super(); }
public IndexedArraySet(Iterable<E> c) {
super();
addAll(c);
}
private HashMap<E, Integer> indexMap = new HashMap<>();
private void reindex() {
indexMap.clear();
int idx = 0;
for (E item: this) {
addToIndex(item, idx++);
}
}
private E addToIndex(E e, int idx) {
indexMap.putIfAbsent(requireNonNull(e), idx);
return e;
}
@Override
public boolean add(E e) {
if(indexMap.putIfAbsent(requireNonNull(e), size()) != null) return false;
super.add(e);
return true;
}
@Override
public boolean addAll(Collection<? extends E> c) {
return addAll((Iterable<? extends E>) c);
}
public boolean addAll(Iterable<? extends E> c) {
boolean rv = false;
for (E item: c) {
rv |= add(item);
}
return rv;
}
@Override
public boolean contains(Object e) {
return indexMap.containsKey(e);
}
@Override
public int indexOf(Object e) {
if (e == null) return -1;
Integer i = indexMap.get(e);
return (i == null) ? -1 : i;
}
@Override
public int lastIndexOf(Object e) {
return indexOf(e);
}
@Override @SuppressWarnings("unchecked")
public Object clone() {
IndexedArraySet clone = (IndexedArraySet) super.clone();
clone.indexMap = (HashMap) indexMap.clone();
return clone;
}
@Override
public void add(int idx, E e) {
if(indexMap.putIfAbsent(requireNonNull(e), -1) != null) return;
super.add(idx, e);
reindex();
}
@Override
public boolean remove(Object e) {
boolean rv;
try { rv = super.remove(e); }
finally { reindex(); }
return rv;
}
@Override
public void clear() {
super.clear();
indexMap.clear();
}
@Override
public boolean addAll(int idx, Collection<? extends E> c) {
boolean rv;
try {
for(E item : c) {
// check uniqueness
addToIndex(item, -1);
}
rv = super.addAll(idx, c);
} finally {
reindex();
}
return rv;
}
@Override
public boolean removeAll(Collection<?> c) {
boolean rv;
try { rv = super.removeAll(c); }
finally { reindex(); }
return rv;
}
@Override
public boolean retainAll(Collection<?> c) {
boolean rv;
try { rv = super.retainAll(c); }
finally { reindex(); }
return rv;
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
boolean rv;
try { rv = super.removeIf(filter); }
finally { reindex(); }
return rv;
}
@Override
public void replaceAll(final UnaryOperator<E> operator) {
indexMap.clear();
try {
int duplicates = 0;
for (int i = 0; i < size(); i++) {
E newval = requireNonNull(operator.apply(this.get(i)));
if(indexMap.putIfAbsent(newval, i-duplicates) == null) {
super.set(i-duplicates, newval);
} else {
duplicates++;
}
}
removeRange(size()-duplicates, size());
} catch (Exception ex) {
// If there's an exception the indexMap will be inconsistent
reindex();
throw ex;
}
}
@Override
public void sort(Comparator<? super E> c) {
try { super.sort(c); }
finally { reindex(); }
}
}