是否可以定义固定大小为100的列表?如果不是为什么在Java中没有这个?
答案 0 :(得分:34)
如果内存服务,这应该这样做:
List<MyType> fixed = Arrays.asList(new MyType[100]);
答案 1 :(得分:27)
您的问题是错误的,或者您对Java List
的心理模型不正确。
Java列表是对象的集合......列表的元素。列表的大小是该列表中元素的数量。如果您希望修复该大小,则意味着您无法添加或删除元素,因为添加或删除元素会违反“固定大小”约束。
实现“固定大小”列表的最简单方法(如果这真的是你想要的!)是将元素放入数组中,然后Arrays.asList(array)
创建列表包装器。包装器允许您执行get
和set
等操作,但add
和remove
操作将抛出异常。
如果要为现有列表创建固定大小的包装器,则可以使用Apache commons FixedSizeList
类。但请注意,此包装器无法阻止其他更改原始列表大小的内容,如果发生这种情况,则包装列表可能会反映这些更改。 (IMO,FixedSizeList
的javadoc很糟糕。它没有尝试记录更改包装列表时类的行为。你需要阅读源代码......并希望它们不会改变当你不注意时的行为。)
另一方面,如果你真的想要一个对其大小有固定限制(或限制)的列表类型,那么你需要创建自己的List类来实现它。例如,您可以创建一个包装类,该类在各种add
/ addAll
和remove
/ removeAll
/ retainAll
操作中实现相关检查。 (如果支持它们,则使用迭代器remove
方法。)
那么为什么Java Collections框架没有实现这些呢?这就是为什么我这么认为:
Collections.sort
。答案 2 :(得分:17)
是强>,
Commons library提供内置FixedSizeList
,不支持add
,remove
和clear
方法(但允许使用set方法,因为它不会修改List
的大小。换句话说,如果您尝试调用其中一种方法,则列表仍保持相同的大小。
要创建固定尺寸列表,只需致电
List<YourType> fixed = FixedSizeList.decorate(Arrays.asList(new YourType[100]));
如果您想要指定列表的不可修改的视图,或者对内部列表的只读访问,则可以使用unmodifiableList
。
List<YourType> unmodifiable = java.util.Collections.unmodifiableList(internalList);
答案 3 :(得分:13)
是。您可以将java数组传递给Arrays.asList(Object[])。
List<String> fixedSizeList = Arrays.asList(new String[100]);
您不能将新的字符串插入fixedSizeList(它已经有100个元素)。您只能设置如下值:
fixedSizeList.set(7, "new value");
这样你有一个固定的大小列表。这个东西就像一个数组,我想不出一个使用它的好理由。我很想知道为什么你希望固定大小的集合成为一个列表,而不是仅使用数组。
答案 4 :(得分:8)
通常,固定大小列表的替代方法是Java数组。默认情况下,列表允许在Java中增长/缩小。但是,这并不意味着您不能拥有固定大小的列表。您需要做一些工作并创建自定义实现。
您可以使用clear,add和remove方法的自定义实现来扩展ArrayList。
e.g。
import java.util.ArrayList;
public class FixedSizeList<T> extends ArrayList<T> {
public FixedSizeList(int capacity) {
super(capacity);
for (int i = 0; i < capacity; i++) {
super.add(null);
}
}
public FixedSizeList(T[] initialElements) {
super(initialElements.length);
for (T loopElement : initialElements) {
super.add(loopElement);
}
}
@Override
public void clear() {
throw new UnsupportedOperationException("Elements may not be cleared from a fixed size List.");
}
@Override
public boolean add(T o) {
throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead.");
}
@Override
public void add(int index, T element) {
throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead.");
}
@Override
public T remove(int index) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
}
答案 5 :(得分:3)
创建一个大小为100的数组。如果需要List接口,请在其上调用Arrays.asList。它将返回由数组支持的固定大小的列表。
答案 6 :(得分:2)
如果您想要一些灵活性,请创建一个监视列表大小的类。
这是一个简单的例子。您需要覆盖更改列表状态的所有方法。
public class LimitedArrayList<T> extends ArrayList<T>{
private int limit;
public LimitedArrayList(int limit){
this.limit = limit;
}
@Override
public void add(T item){
if (this.size() > limit)
throw new ListTooLargeException();
super.add(item);
}
// ... similarly for other methods that may add new elements ...
答案 7 :(得分:1)
您可以定义如下通用函数:
@SuppressWarnings("unchecked")
public static <T> List<T> newFixedSizeList(int size) {
return (List<T>)Arrays.asList(new Object[size]);
}
和
List<String> s = newFixedSizeList(3); // All elements are initialized to null
s.set(0, "zero");
s.add("three"); // throws java.lang.UnsupportedOperationException
答案 8 :(得分:1)
这应该很好。它永远不会超过初始大小。 toList方法将按正确的时间顺序为您提供条目。这是在groovy中完成的-但是将其正确转换为Java应该很容易。
static class FixedSizeCircularReference<T> {
T[] entries
FixedSizeCircularReference(int size) {
this.entries = new Object[size] as T[]
this.size = size
}
int cur = 0
int size
void add(T entry) {
entries[cur++] = entry
if (cur >= size) {
cur = 0
}
}
List<T> asList() {
List<T> list = new ArrayList<>()
int oldest = (cur == size - 1) ? 0 : cur
for (int i = 0; i < this.entries.length; i++) {
def e = this.entries[oldest + i < size ? oldest + i : oldest + i - size]
if (e) list.add(e)
}
return list
}
}
FixedSizeCircularReference<String> latestEntries = new FixedSizeCircularReference(100)
latestEntries.add('message 1')
// .....
latestEntries.add('message 1000')
latestEntries.asList() //Returns list of '100' messages
答案 9 :(得分:0)
如果您想使用ArrayList或LinkedList,似乎答案是肯定的。尽管java中有一些类可以设置固定大小,如PriorityQueue,但ArrayList和LinkedList不能,因为这两个类没有构造函数来指定容量。
如果你想坚持使用ArrayList / LinkedList,一个简单的解决方案是每次都手动检查大小。
public void fixedAdd(List<Integer> list, int val, int size) {
list.add(val);
if(list.size() > size) list.remove(0);
}
在这种情况下,LinkedList优于ArrayList。假设要添加许多值但列表大小非常小,将会有许多删除操作。原因是从ArrayList中删除的成本是O(N),但是对于LinkedList只有O(1)。
答案 10 :(得分:0)
JDK的公共java.util.List
子类没有提供不属于List
specification的一部分的固定大小功能。
您只能在处理非常具体的要求的Queue
子类(例如ArrayBlockingQueue
,例如由数组支持的有界阻塞队列)中找到它。
在Java中,List
类型的代码可以根据两种情况实现:
1)固定列表大小始终是实际大小和最大大小。
听起来像是数组定义。因此,Arrays.asList()
返回的是您要查找的,由指定数组支持的固定大小列表。与数组一样,您不能增加或减小其大小,而只能更改其内容。因此,不支持添加和删除操作。
例如:
Foo[] foosInput= ...;
List<Foo> foos = Arrays.asList(foosInput);
foos.add(new Foo()); // throws an Exception
foos.remove(new Foo()); // throws an Exception
它也可以作为集合的输入,首先我们将其转换为数组:
Collection<Foo> foosInput= ...;
List<Foo> foos = Arrays.asList(foosInput.toArray(Foo[]::new)); // Java 11 way
// Or
List<Foo> foos = Arrays.asList(foosInput.stream().toArray(Foo[]::new)); // Java 8 way
2)列表内容一创建就不知道。因此,您的意思是按固定大小列出其最大大小。
您可以使用继承(extends ArrayList
),但您应该更喜欢使用组合,因为它可以让您不将类与该实现的实现细节相结合,并且还提供了修饰/组成的实现的灵活性。
有了Guava Forwarding classes,您可以做到:
import com.google.common.collect.ForwardingList;
public class FixedSizeList<T> extends ForwardingList<T> {
private final List<T> delegate;
private final int maxSize;
public FixedSizeList(List<T> delegate, int maxSize) {
this.delegate = delegate;
this.maxSize = maxSize;
}
@Override protected List<T> delegate() {
return delegate;
}
@Override public boolean add(T element) {
assertMaxSizeNotReached(1);
return super.add(element);
}
@Override public void add(int index, T element) {
assertMaxSizeNotReached(1);
super.add(index, element);
}
@Override public boolean addAll(Collection<? extends T> collection) {
assertMaxSizeNotReached(collection.size());
return super.addAll(collection);
}
@Override public boolean addAll(int index, Collection<? extends T> elements) {
assertMaxSizeNotReached(elements.size());
return super.addAll(index, elements);
}
private void assertMaxSizeNotReached(int size) {
if (delegate.size() + size >= maxSize) {
throw new RuntimeException("size max reached");
}
}
}
并使用它:
List<String> fixedSizeList = new FixedSizeList<>(new ArrayList<>(), 3);
fixedSizeList.addAll(Arrays.asList("1", "2", "3"));
fixedSizeList.add("4"); // throws an Exception
请注意,对于合成,您可以将其与任何List
实现一起使用:
List<String> fixedSizeList = new FixedSizeList<>(new LinkedList<>(), 3);
//...
继承是不可能的。
答案 11 :(得分:0)
是可以的:
List<Integer> myArrayList = new ArrayList<>(100);
现在,myArrayList的初始容量为100
答案 12 :(得分:0)
根据传递给构建器的 T
元素的容器类型(Collection<T>
或 T[]
),您需要以下任一项:
Collection<T> YOUR_COLLECTION
:Collections.unmodifiableList(new ArrayList<>(YOUR_COLLECTION));
T[] YOUR_ARRAY
:Arrays.asList(YOUR_ARRAY);
就这么简单