存储并查找某个数组是否已经存储
Store and find if a certain array is already stored
我的程序检查了多个布尔数组(每个长度为 30),我想知道我是否已经检查过那个数组。我认为处理这个问题的最好方法是存储所有数组并在所有数组的集合中搜索新数组,但我不知道我应该使用什么结构。起初,我虽然 hashtable 是最好的,但看起来我不能将它们与数组一起使用。我找了 set 和 list,但我不知道该用什么!
Edit/clarification:嘿,这是我的第一个问题,我很惊讶我收到了这么多答案,非常感谢!很多人说他们不确定我到底在寻找什么,所以我会尝试澄清一下:
我有多个长度为 30 的布尔数组,其中顺序很重要(数组中元素的顺序)。
我一次收到一个数组,我想检查我是否已经收到相同的数组(相同的元素,相同的顺序)。我不需要存储它们(我不需要任何索引,我不想知道我收到了多少数组),除了知道我是否已经收到数组之外不需要任何东西。
你可以使用数组:)
如果您有 n 个数组,则创建一个大小为 n 的布尔数组。我们称它为 checked[]。
所以如果选中[5] == true,则您已经选中了第五个数组。
另一种选择是使用每个数组的索引 0 作为 'checked flag'。
您可以尝试使用邻接列表或者您调用 'Pair' 的对象的 array/arraylist 例如,其中此对象有两个属性,第一个是数组(您检查的数组或还没有检查),第二个属性是一个布尔值,表示这个数组是否被访问过。
您可以创建一个 Wrapper class
来保存数组(内容)和一个标志。而且,您可以存储此 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
(内容)后将 checked 设置为 true。
使用Arrays.equals(array1, array2)
如果指定的两个布尔数组彼此相等,则此方法returns为真。如果两个数组包含相同数量的元素,并且两个数组中所有对应的元素对都相等,则认为两个数组相等。
我给你一个暴力解法
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);
}
}
感谢您的澄清!
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;
}
布尔数组基本上是一个位列表。由于数组大小为 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));
}
这提供了一个非常快速且低内存的实现,可以处理大量布尔数组。
我的程序检查了多个布尔数组(每个长度为 30),我想知道我是否已经检查过那个数组。我认为处理这个问题的最好方法是存储所有数组并在所有数组的集合中搜索新数组,但我不知道我应该使用什么结构。起初,我虽然 hashtable 是最好的,但看起来我不能将它们与数组一起使用。我找了 set 和 list,但我不知道该用什么!
Edit/clarification:嘿,这是我的第一个问题,我很惊讶我收到了这么多答案,非常感谢!很多人说他们不确定我到底在寻找什么,所以我会尝试澄清一下:
我有多个长度为 30 的布尔数组,其中顺序很重要(数组中元素的顺序)。
我一次收到一个数组,我想检查我是否已经收到相同的数组(相同的元素,相同的顺序)。我不需要存储它们(我不需要任何索引,我不想知道我收到了多少数组),除了知道我是否已经收到数组之外不需要任何东西。
你可以使用数组:)
如果您有 n 个数组,则创建一个大小为 n 的布尔数组。我们称它为 checked[]。
所以如果选中[5] == true,则您已经选中了第五个数组。
另一种选择是使用每个数组的索引 0 作为 'checked flag'。
您可以尝试使用邻接列表或者您调用 'Pair' 的对象的 array/arraylist 例如,其中此对象有两个属性,第一个是数组(您检查的数组或还没有检查),第二个属性是一个布尔值,表示这个数组是否被访问过。
您可以创建一个 Wrapper class
来保存数组(内容)和一个标志。而且,您可以存储此 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
(内容)后将 checked 设置为 true。
使用Arrays.equals(array1, array2)
如果指定的两个布尔数组彼此相等,则此方法returns为真。如果两个数组包含相同数量的元素,并且两个数组中所有对应的元素对都相等,则认为两个数组相等。
我给你一个暴力解法
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);
}
}
感谢您的澄清!
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;
}
布尔数组基本上是一个位列表。由于数组大小为 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));
}
这提供了一个非常快速且低内存的实现,可以处理大量布尔数组。