在java中删除数组中的元素可以将其设置为null吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1777126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In java to remove an element in an array can you set it to null?
提问by Ben Fossen
I am trying to make a remove method that works on an array implementation of a list. Can I set the the duplicate element to null to remove it? Assuming that the list is in order.
我正在尝试创建一个适用于列表的数组实现的 remove 方法。我可以将重复元素设置为 null 以将其删除吗?假设列表是有序的。
ArrayList a = new ArrayList[];
public void removeduplicates(){
for(a[i].equals(a[i+1]){
a[i+1] = null;
}
a[i+1] = a[i];
}
采纳答案by R. Martinho Fernandes
No you can't remove an element from an array, as in making it shorter. Java arrays are fixed-size. You need to use an ArrayList
for that.
不,你不能从数组中删除一个元素,就像让它变短一样。Java 数组是固定大小的。你需要使用一个ArrayList
。
If you set an element to null, the array will still have the same size, but with a null reference at that point.
如果您将一个元素设置为 null,该数组仍将具有相同的大小,但此时引用为 null。
// Let's say a = [0,1,2,3,4] (Integer[])
a[2] = null;
// Now a = [0,1,null,3,4]
回答by Mark Byers
Yes, you can set elements in an array to null, but code like a[i].equals(a[i+1])
will fail with a NullPointerException if the array contains nulls, so you just have to be more careful if you know that your array may contain nulls. It also doesn't change the size of the array so you will be wasting memory if you remove large numbers of elements. Fixed size arrays are generally not a good way to store data if you are often adding and removing elements - as you can guess from their name.
是的,您可以将数组中的元素设置为空,但是a[i].equals(a[i+1])
如果数组包含空值,类似的代码将失败并返回 NullPointerException,因此如果您知道数组可能包含空值,则必须更加小心。它也不会改变数组的大小,因此如果删除大量元素,则会浪费内存。如果您经常添加和删除元素,固定大小的数组通常不是存储数据的好方法 - 正如您可以从它们的名称猜到的那样。
回答by Carl Smotricz
No, an array element containing a null
is still there, it just doesn't contain any useful value.
不,包含 a 的数组元素null
仍然存在,它只是不包含任何有用的值。
You could try moving every element from further down in the list up by 1 element to fill the gap, then you have a gap at the end of the array - the array will not shrink from doing this!
您可以尝试将列表中的每个元素从更靠后的位置向上移动 1 个元素以填补空白,然后在数组的末尾有一个空白 - 数组不会因这样做而缩小!
If you're doing this a lot, you can use System.arraycopy()
to do this packing operation quickly.
如果您System.arraycopy()
经常这样做,您可以使用快速完成此打包操作。
回答by Vargen
Use ArrayList.remove(int index).
使用 ArrayList.remove(int index)。
if(a[i].equals(foo()))
a.remove(i)
But be careful when using for-loops and removing objects in arrays.
但是在使用 for 循环和删除数组中的对象时要小心。
http://java.sun.com/j2se/1.3/docs/api/java/util/ArrayList.html
http://java.sun.com/j2se/1.3/docs/api/java/util/ArrayList.html
回答by Pascal Thivent
Can I set the the duplicate element to null to remove it?
我可以将重复元素设置为 null 以将其删除吗?
You can set an element of the array null
but this doesn't remove the element of the array... it just set the element to null
(I feel like repeating the first sentence).
您可以设置数组的一个元素,null
但这不会删除数组的元素......它只是将元素设置为null
(我觉得要重复第一句话)。
You should return a cleaned copy of the array instead. One way to do this would be to use an intermediary java.util.Set
:
您应该返回一个清理过的数组副本。一种方法是使用中介java.util.Set
:
String[] data = {"A", "C", "B", "D", "A", "B", "E", "D", "B", "C"};
// Convert to a list to create a Set object
List<String> list = Arrays.asList(data);
Set<String> set = new HashSet<String>(list);
// Create an array to convert the Set back to array.
String[] result = new String[set.size()];
set.toArray(result);
Or maybe just use a java.util.Set
:)
或者也许只是使用一个java.util.Set
:)
回答by Stephen C
The straight-forward answer to your question is that setting an array or ArrayList element to null gives you a null entry in the array or ArrayList. This is not the same thing as removing the element. If just means that a[i]
or a.get(i)
will return null
rather than the original element.
对您的问题的直接回答是,将数组或 ArrayList 元素设置为 null 会在数组或 ArrayList 中为您提供一个空条目。这与删除元素不同。如果只是意味着a[i]
或a.get(i)
将返回null
而不是原始元素。
The code in the question is garbled. If you are going to use an ArrayList, the simplisitic solution would be something like this:
问题中的代码是乱码。如果您打算使用 ArrayList,那么简单的解决方案将是这样的:
ArrayList a = new ArrayList();
public void removeduplicates() {
for (int i = 0; i < a.size() - 1; ) {
if (a.get(i).equals(a.get(i + 1)) {
a.remove(i);
} else {
i++;
}
}
}
but in the worst case, that is O(N**2)
because each call to remove
copies all elements at indexes greater than the current value of i
.
但在最坏的情况下,这是O(N**2)
因为每次调用都会remove
复制索引大于 的当前值的所有元素i
。
If you want to improve the performance, do something like this:
如果您想提高性能,请执行以下操作:
public ArrayList removeduplicates() {
ArrayList res = new ArrayList(a.size());
if (a.size() == 0) {
return res;
}
res.add(a.get(0));
for (int i = 1; i < a.size(); i++) {
if (!a.get(i - 1).equals(a.get(i)) {
res.add(a.get(i));
}
}
return res;
}
(This is a quick hack. I'm sure it could be tidied up.)
(这是一个快速的技巧。我相信它可以整理。)
回答by seh
Is this a homework question?
这是家庭作业问题吗?
Your problem is analogous to the stream processing program uniq
: Preserve -- by way of copying -- any element that doesn't match the one before it. It only removes allduplicates if the sequence is sorted. Otherwise, it only removes contiguousduplicates. That means you need to buffer at most one element (even if by reference) to use as a comparison predicate when deciding whether to keep an element occurring later in the sequence.
您的问题类似于流处理程序uniq
:保留——通过复制——任何与其之前的元素不匹配的元素。如果序列已排序,它只会删除所有重复项。否则,它只会删除连续的重复项。这意味着您最多需要缓冲一个元素(即使是通过引用),以便在决定是否保留序列中稍后出现的元素时用作比较谓词。
The only special case is the first element. As it should never match any preceding element, you can try to initialize your buffered "previous" element to some value that's out of the domain of the sequence type, or you can special-case your iteration with a "first element" flag or explicitly copy the first element outside the iteration -- minding the case where the sequence is empty, too.
唯一的特殊情况是第一个元素。由于它永远不应该匹配任何前面的元素,因此您可以尝试将缓冲的“前一个”元素初始化为序列类型域之外的某个值,或者您可以使用“第一个元素”标志或显式地对迭代进行特殊处理复制迭代之外的第一个元素——也要注意序列为空的情况。
Note that I did not propose you provide this operation as a destructive in-place algorithm. That would only be appropriate with a structure like a linked list with constant-time overhead for removing an element. As others note here, removing an element from an array or vector involves shuffling down successor elements to "fill the hole", which is of time complexity nin the number of successors.
请注意,我不建议您将此操作作为破坏性就地算法提供。这仅适用于像链表这样的结构,它具有用于删除元素的恒定时间开销。正如其他人在此处指出的那样,从数组或向量中删除元素涉及对后继元素进行混洗以“填补空洞”,其时间复杂度为n 的后继元素。
回答by BalusC
Your code example was quite confusing. With ArrayList[]
you showed an array of ArrayList objects.
您的代码示例非常令人困惑。与ArrayList[]
您一起展示了一组 ArrayList 对象。
Assuming that you're talking about just the java.util.ArrayList
, then the most easy way to get rid of duplicates is to use a java.util.Set
instead, as mentioned by others. If you really want to have, startwith, or end up with a List
for some reasons then do:
假设你只是在谈论java.util.ArrayList
,那么摆脱重复的最简单方法是使用 ajava.util.Set
代替,正如其他人提到的那样。如果您List
出于某些原因真的想要拥有、开始或结束,那么请执行以下操作:
List withDuplicates = new ArrayList() {{ add("foo"); add("bar"); add("waa"); add("foo"); add("bar"); }}; // Would rather have used Arrays#asList() here, but OK.
List withoutDuplicates = new ArrayList(new LinkedHashSet(withDuplicates));
System.out.println(withoutDuplicates); // [foo, bar, waa]
The LinkedHashSet
is chosen here because it maintains the ordering. If you don't worry about the ordering, a HashSet
is faster. But if you actually want to have it sorted, a TreeSet
may be more of value.
在LinkedHashSet
这里选择 是因为它保持排序。如果您不担心订购,aHashSet
会更快。但是,如果您真的想对其进行排序,则 aTreeSet
可能更有价值。
On the other hand, if you're talking about a real arrayand you want to filter duplicates out of this without help of the (great) Collections framework, then you'd need to create another array and add items one by one to it while you check if the array doesn't already contain the to-be-added item. Here's a basic example (without help of Arrays.sort()
and Arrays.binarySearch()
which would have eased the task more, but then you would end up with a sorted array):
另一方面,如果你在谈论一个真正的数组并且你想在没有(伟大的)集合框架的帮助下从中过滤重复项,那么你需要创建另一个数组并一个一个地向它添加项目当您检查数组是否已包含要添加的项目时。这是一个基本示例(没有Arrays.sort()
和 的帮助,Arrays.binarySearch()
这会使任务更加轻松,但最终会得到一个排序数组):
String[] array1 = new String[] {"foo", "bar", "foo", "waa", "bar"};
String[] array2 = new String[0];
loop:for (String array1item : array1) {
for (String array2item : array2) {
if (array1item.equals(array2item)) {
continue loop;
}
}
int length = array2.length;
String[] temp = new String[length + 1];
System.arraycopy(array2, 0, temp, 0, length);
array2 = temp;
array2[length] = array1item;
}
System.out.println(Arrays.toString(array2)); // [foo, bar, waa]
Hope this gives new insights.
希望这能提供新的见解。
回答by Blessed Geek
If you are implementing your own list and you have decide to use a basic primitives storage mechanism. So using an array (rather than an arraylist) could be where you start.
如果您正在实现自己的列表并且您决定使用基本的原语存储机制。因此,您可以从使用数组(而不是数组列表)开始。
For a simple implementation, your strategy should consider the following.
对于简单的实施,您的策略应考虑以下内容。
Decide how to expand your list. You could instantiate data blocks of 200 cells at a time. You would only use 199 because you might want to use the last cell to store the next allocation block.
决定如何扩展您的列表。您可以一次实例化 200 个单元格的数据块。您将只使用 199,因为您可能希望使用最后一个单元格来存储下一个分配块。
Such linked list are horrible so you might decide to use a master block to store all the instances of blocks. You instantiate a master block of size 100. You start with one data block of 200 and store its ref in master[0]. As the list grows in size, you progressively store the ref of each new data blocks in master[1] .... master[99] and then you might have to recreate the master list to store 200 references.
这样的链表很糟糕,所以你可能决定使用一个主块来存储块的所有实例。您实例化一个大小为 100 的主块。您从一个 200 的数据块开始,并将其引用存储在 master[0] 中。随着列表大小的增长,您逐渐将每个新数据块的引用存储在 master[1] .... master[99] 中,然后您可能必须重新创建主列表以存储 200 个引用。
For the reason of efficiency, when you delete a cell, you should not actually exterminate it immediately. You let it hang around until enough deletion has occurred for you to recreate the block.
出于效率的考虑,当您删除一个单元格时,实际上不应立即将其消灭。您让它一直存在,直到发生足够的删除以重新创建块。
You need to somehow flag a cell has been deleted. So the answer is obvious, of course you can set it to null because you are the king, the emperor, the dictator who decides how a cell is flagged as deleted. Using a null is a great and usual way. If you use null, then you have to disallow nulls from being inserted as data into your list class. You would have to throw an exception when such an attempt is made.
您需要以某种方式标记单元格已被删除。所以答案是显而易见的,当然您可以将其设置为 null,因为您是国王、皇帝、决定如何将单元格标记为已删除的独裁者。使用 null 是一种很好的常用方法。如果使用 null,则必须禁止将 null 作为数据插入到列表类中。进行此类尝试时,您将不得不抛出异常。
You have to design and write a garbage collection routine and strategy to compact the list by recreating blocks to remove nullified cells en mass. The JVM would not know those are "deleted" data.
您必须设计和编写垃圾收集例程和策略,通过重新创建块以大量删除无效单元来压缩列表。JVM 不会知道那些是“已删除”的数据。
You need a register to count the number of deletions and if that threshold is crossed, garbage collection would kick in. Or you have the programmer decide to invoke a compact() method. Because if deletions are sparse and distributed across various data blocks, might as well leave the null/deleted cells hang around. You could only merge adjacent blocks and only if the sum of holes in both blocks count up to 200, obviously.
您需要一个寄存器来计算删除次数,如果超过该阈值,垃圾收集就会启动。或者您让程序员决定调用一个 compact() 方法。因为如果删除是稀疏的并且分布在各个数据块中,那么可能会留下空/已删除的单元格。显然,您只能合并相邻的块,并且仅当两个块中的孔总和达到 200 时。
Perhaps, when data is appended to a list, you deliberately leave null holes in between the data. It's like driving down the street and you see house addresses incremented by ten because the the city has decided that if people wish to build new houses in between existing houses. In that way you don't have to recreate and split a block every time an insertion occurs.
也许,当数据附加到列表时,您故意在数据之间留下空洞。这就像在街上开车,您会看到房屋地址增加了 10,因为该市已经决定,如果人们希望在现有房屋之间建造新房屋。这样您就不必在每次插入时重新创建和拆分块。
Therefore, the answer is obvious to yourself, of course you can write null to signify a cell is deleted, because it is your strategy in managing the list class.
因此,答案对你自己来说是显而易见的,当然你可以写 null 来表示一个单元格被删除,因为这是你管理列表类的策略。