存储并查找是不是已经存储了某个数组
Posted
技术标签:
【中文标题】存储并查找是不是已经存储了某个数组【英文标题】:Store and find if a certain array is already stored存储并查找是否已经存储了某个数组 【发布时间】:2016-07-20 11:23:35 【问题描述】:我的程序检查多个布尔数组(每个长度为 30),我想知道我是否已经检查过该数组。我认为处理这个问题的最佳方法是存储所有数组并在所有数组的集合中搜索新数组,但我不知道应该使用什么结构。起初,我认为哈希表是最好的,但看起来我不能将它们与数组一起使用。我找了 set 和 list 但我不知道该用什么!
编辑/澄清:嘿,这是我在这里的第一个问题,我很惊讶我收到了多少答案,非常感谢!很多人说他们不确定我到底在寻找什么,所以我会试着澄清一下:
我有多个长度为 30 的布尔数组,其中顺序很重要(数组中元素的顺序)。
我一次收到一个数组,我想检查我是否已经收到了相同的数组(相同的元素,相同的顺序)。我不需要存储它们(我不需要任何索引,我不想知道我收到了多少个数组),除了知道我是否已经收到数组之外什么都不需要。
【问题讨论】:
为检查数组设置标志。前任。定义了一个布尔值,例如 isChecked.... 你能把你的数组转换成列表吗?使用 java.util.Arrays 中的 'public static你可以使用数组:)
如果您有 n 个数组,则创建一个大小为 n 的布尔数组。我们称它为checked[]。
所以如果checked[5] == true,你已经检查了第五个数组。
另一种选择是将每个数组的索引 0 用作“已检查标志”。
【讨论】:
输入是boolean[30]
,问题是这个特定的数组以前是否见过。【参考方案2】:
您可以尝试使用邻接列表或您称为“配对”的对象的数组/数组列表,例如该对象有两个属性,第一个是数组(您检查或尚未检查的数组)第二个属性是一个布尔值,表示这个数组是否被访问过。
【讨论】:
【参考方案3】:您可以创建一个 Wrapper class
来保存数组(内容)和一个标志。并且,您可以存储此类对象的array
,而不是存储数组数组。看看下面的例子:
public class ArrayWrapper
private boolean checked;
private boolean[] content;
/**
* @return the checked
*/
public boolean isChecked()
return checked;
/**
* @param checked the checked to set
*/
public void setChecked(boolean checked)
this.checked = checked;
/**
* @return the content
*/
public boolean[] getContent()
return content;
/**
* @param content the content to set
*/
public void setContent(boolean[] content)
this.content = content;
现在,您可以创建一个List<ArrayWrapper>
或ArrayWrapper[]
,遍历它并在检查array
(内容)后将其设置为true。
【讨论】:
【参考方案4】:使用Arrays.equals(array1, array2)
如果两个指定的布尔数组彼此相等,则此方法返回 true。如果两个数组包含相同数量的元素,并且两个数组中所有对应的元素对相等,则认为两个数组相等。
我给你一个蛮力解决方案。
List<boolean[]> arrs = new ArrayList<>();
while (true)
boolean[] receivedArr = receive();
for (boolean[] existingArr : arrs)
if (Arrays.equals(existingArr, receivedArr))
drop(receivedArr);
break;
arrs.add(receivedArr);
【讨论】:
【参考方案5】:感谢您的澄清!
HashMap 仍然是使用 Arrays.hashCode() 创建密钥对象的好答案。像这样:
HashMap<Integer, Boolean> checked = new HashMap<>();
/**
* Returns true if already checked; false if it's new
*/
public boolean isChecked(Boolean [] array)
int hashCode = Arrays.hashCode(array);
Boolean existing = checked(hashCode);
if (existing == null)
checked.put(hashCode, true);
return true;
return false;
【讨论】:
@KeqiangLi 他对他的帖子的评论说“我想搜索两个数组是否相等(对于多个数组)”澄清了这一点。 Arrays.hashCode() 方法将满足相等性要求。 他还说'检查是否有一个相等的数组(所有相同的元素,以相同的顺序)' @z000by 感谢您的澄清!查看我修改后的答案。hashCode()
不保证唯一性,因此两个不同的布尔数组可能具有相同的哈希码。因此,以哈希码为键的映射可能会产生误报。【参考方案6】:
布尔数组基本上是一个位列表。由于数组大小为 30,而 int
是 32 位值,因此您可以将数组转换为 int
。使用long
,您可以支持最大为 64 的数组。
所以,首先将您的数组转换为int
:
private static int toBits(boolean[] array)
if (array.length > 32)
throw new IllegalArgumentException("Array too large: " + array.length);
int bits = 0;
for (int i = 0; i < array.length; i++)
if (array[i])
bits |= 1 << i;
return bits;
然后使用Set<Integer>
跟踪:
private Set<Integer> alreadySeen = new HashSet<>();
private boolean firstTime(boolean[] array)
return ! this.alreadySeen.add(toBits(array));
这提供了一个非常快速且低内存的实现,可以处理大量布尔数组。
【讨论】:
这绝对是一个更聪明的解决方案。 +1 看起来非常好,谢谢!最后一个问题,如果我必须将数组转换为 int,我将遍历数组,将索引处的值乘以 10*index:(true, false true) = 1 + 10*0 + 100*1 = 101。看起来您使用的是不同的技术,或者只是另一种表示法?转换位的最佳方法是什么。 @z000by 不懂评论。我已经给出了将数组转换为int
的实现,它使用1 << i
,而不是乘以10。位是base-2逻辑,而不是base-10。
我会用 google 1
@z000by 请参阅 Bitwise and Bit Shift Operators(Java™ 教程)、How does bitshifting work in Java?(***)、Bitwise operation - Bit shifts(***)。以上是关于存储并查找是不是已经存储了某个数组的主要内容,如果未能解决你的问题,请参考以下文章