如果有人熟悉Objective-C中有一种叫做集合NSOrderedSet
,它充当一个集及其项目可以作为访问数组的人。
Java中有类似的东西吗?
我听说有一个名为的集合LinkedHashMap
,但没有找到类似的集合。
如果有人熟悉Objective-C中有一种叫做集合NSOrderedSet
,它充当一个集及其项目可以作为访问数组的人。
Java中有类似的东西吗?
我听说有一个名为的集合LinkedHashMap
,但没有找到类似的集合。
Answers:
Set接口的哈希表和链表实现,迭代顺序可预测。此实现与HashSet的不同之处在于,它维护一个贯穿其所有条目的双向链接列表。此链表定义了迭代顺序,即将元素插入集合中的顺序(插入顺序)。请注意,如果将元素重新插入到set中,则插入顺序不会受到影响。(如果在调用之前s.contains(e)将返回true的情况下调用s.add(e),则将元素e重新插入到set s中。)
LinkedHashMap
但我还没找到。
LinkedHashSet
可以让您确定元素所在的索引。
每个Set都有一个iterator()。普通的HashSet的迭代器是相当随机的,TreeSet按排序顺序进行,LinkedHashSet迭代器按插入顺序进行迭代。
但是,您不能替换LinkedHashSet中的元素。您可以删除一个并添加另一个,但是新元素将不会代替原始元素。在LinkedHashMap中,您可以替换现有键的值,然后这些值仍将保持原始顺序。
另外,您不能在特定位置插入。
也许您最好使用带有明确检查的ArrayList以避免插入重复项。
LinkedHashSet
应该这样做。感谢您的回覆
看一下Java标准API文档。在旁边LinkedHashMap
,有一个LinkedHashSet
。但是请注意,这些顺序是插入顺序,而不是元素的自然顺序。而且,您只能按此顺序进行迭代,而不能进行随机访问(通过计算迭代步骤除外)。
还有一个SortedSet
由TreeSet
和实现的接口ConcurrentSkipListSet
。两者都允许以其元素的自然顺序或进行迭代Comparator
,但不允许随机访问或插入顺序。
对于既可以通过索引进行有效访问又可以有效实现设置标准的数据结构,则需要一个跳过列表,但是Java Standard API中没有使用该功能的实现,尽管我敢肯定很容易找到一个在网上。
ConcurrentSkipListMap
和ConcurrentSkipListSet
。两者都维护基于自然顺序或比较器的排序。我不知道他们是否提供您讨论的随机访问或进入顺序。
尝试使用java.util.TreeSet
该工具SortedSet
。
引用文档:
“根据元素的自然顺序或在集合创建时提供的Comparator来对元素进行排序,这取决于所使用的构造函数”
请注意,添加,删除和包含具有时间成本log(n)。
如果要以数组形式访问集合的内容,可以执行以下操作将其转换:
YourType[] array = someSet.toArray(new YourType[yourSet.size()]);
该数组将使用与TreeSet相同的条件进行排序(自然排序或通过比较器排序),在许多情况下,这比不执行Arrays.sort()有优势。
c
,然后元素a
,因为我遍历整个集合我想,让他们在同一顺序:c
,a
等等
IndexedTreeSet从索引树地图项目提供了这种功能(订购/排序设置与列表类似的索引访问)。
我有一个类似的问题。我不是很需要有序集合,而是更多带有快速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(); }
}
}