仅当参数对象是调用对象的子集时,此函数才应返回true,但始终返回true。如何解决?
public boolean contains(FileCollection other) {
int i = 0;
int j = 0;
for (i = 0; i<other.files.length; i++) {
for (j = 0; j<this.files.length; j++) {
if ((other.files[i]).equals((this.files[j]))) //this refers to the equals method defined in File class
break;
}
if (j==this.files.length)
return false;
}
return true;//this method is in FileCollection class
}
答案 0 :(得分:3)
(因为您没有明确表示数组元素的数据类型是什么,所以我假设它是File
,从注释中推断出来。)
如果您不介意在数据结构之间进行转换,则将数组(临时)转换为Collections是最简单的方法。例如,转换为List
:
/* @param other
* @return true if the calling object contains
* all files in the parameter object, false otherwise
*/
public boolean contains(FileCollection other) {
List<File> myList = Arrays.asList(this.files);
List<File> otherList = Arrays.asList(other.files);
return myList.containsAll(otherList);
}
基于您对允许重复项时被视为“包含”的澄清,我想您需要计算每个元素的存在数量。方法如下:
基于@Eritrean的答案,您可以获取计数并将其存储到地图。我也进行了修改以检查计数:
public boolean contains(FileCollection other) {
Map<File,Integer> otherFrequency = Arrays.stream(other.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
Map<File,Integer> thisFrequency = Arrays.stream(this.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
if (thisFrequency.entrySet().containsAll(otherFrequency).entrySet()) {
for (File entry : otherFrequency.entrySet()) {
if (thisFrequency.get(entry) < otherFrequency.get(entry))
return false;
}
return true;
}
return false;
}
答案 1 :(得分:2)
要让other.files
包含this.files
,每个this.file
必须在other.files
中。
for (int j = 0; j < this.files.length; j++) {
boolean found = false;
for (int i = 0; i < other.files.length; i++) {
if (other.files[i].equals(this.files[j])) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
您可能不知道files
的类别,
for (String file : this.files) {
boolean found = false;
for (String otherFile : other.files) {
if (otherFile.equals(file)) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
甚至
for (String file : this.files) {
boolean found = other.files.indexOf(file) != -1;
if (!found) {
return false;
}
}
return true;
有更好的数据结构可以加快处理速度,并为contains
之类的事情提供了预定义的方法。
具有重复项
Comparator<File> comparator = new Comparator<File>() {
@Override
public int compare(File lhs, File rhs) {
int cmp = lhs.getBase().compareIgnoreCase(rhs.getBase());
if (cmp == 0) {
cmp = lhs.getExtension().compareIgnoreCase(rhs.getExtension());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getSize(), rhs.getSize());
}
return cmp;
}
};
Arrays.sort(this.files, comparator);
Arrays.sort(other.files, comparator);
int otherI = 0;
for (File file : this.files.length) {
boolean found = false;
while (otherI < other.files.length) {
int comparison = comparator.compare(other.files[otherI], file);
++otherI;
if (comparison >= 0) {
found = comparison == 0;
break;
}
}
if (!found) {
return false;
}
}
return true;
通过对两个数组进行排序,您可以在两个数组中的位置同步比较。上面处理重复项。
答案 2 :(得分:1)
除了@renyuneyun建议将数组转换为列表之外,您还可以使用String
contains
方法
public boolean contains(FileCollection other) {
String myList = Arrays.toString(this.files);
String otherList = Arrays.toString(other.files);
return myList.contains(otherList);
}
当然,从复杂性的角度来看,这两个建议都不是最佳解决方案,但是肯定是最短的:)
答案 3 :(得分:1)
如何使用以File为键,频率为值的地图:
public boolean contains(FileCollection other) {
Map<File,Integer> otherFrequency = Arrays.stream(other.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
Map<File,Integer> thisFrequency = Arrays.stream(this.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
return thisFrequency.entrySet().containsAll(otherFrequency.entrySet());
}
答案 4 :(得分:0)
仅此答案对我有用:(为“比较器”部分致谢@Joop Eggen)
public boolean contains(FileCollection other) {
Comparator<File> comparator = new Comparator<File>() {
@Override
public int compare(File lhs, File rhs) {
int cmp = lhs.getBase().compareToIgnoreCase(rhs.getBase());
if (cmp == 0) {
cmp = lhs.getExtension().compareToIgnoreCase(rhs.getExtension());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getSize(), rhs.getSize());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getPermissions(), rhs.getPermissions());
}
return cmp;
}
};
Arrays.sort(this.files, comparator);
Arrays.sort(other.files, comparator); //THIS AND THE COMPARATOR SORT THE ARRAYS BASED ON ALL FILE ATTRIBUTES
int i = 0;
int j = 0;
if (this.files.length<other.files.length)
return false;
while (i<other.files.length && j<this.files.length) {
if (!(this.files[j].equals(other.files[i])))
j++;
else {
j++;
i++;
}
}
if (i<other.files.length)
return false;
else
return true;
}