Java 生成唯一密钥以避免树映射中的覆盖
我有一个Java 生成唯一密钥以避免树映射中的覆盖,java,sorting,unique,treemap,Java,Sorting,Unique,Treemap,我有一个TreeMap,其中包含的元组,因为我需要按文件大小对其进行排序。这种订货方式非常有效 现在我遇到了一个问题,一个新文件,它的大小与映射中已经存在的另一个文件的大小相同,将用这个新文件名覆盖旧条目 我只是试图通过将TreeMap更改为TreeMap并通过填充键,向TreeMap键添加递增计数器值。然后问题是键的顺序,因为字符串例如9#1会介于89#1和90#1之间,这是错误的,因为文件大小只有9(因此应该在89和90之前) 然后我编写了一个自定义的比较器,它能够按照文件大小(通过删除计数
TreeMap
,其中包含
的元组,因为我需要按文件大小对其进行排序。这种订货方式非常有效
现在我遇到了一个问题,一个新文件,它的大小与映射中已经存在的另一个文件的大小相同,将用这个新文件名覆盖旧条目
我只是试图通过将TreeMap
更改为TreeMap
并通过
填充键,向TreeMap
键添加递增计数器值。然后问题是键的顺序,因为字符串
例如9#1
会介于89#1
和90#1
之间,这是错误的,因为文件大小
只有9(因此应该在89和90之前)
然后我编写了一个自定义的比较器
,它能够按照文件大小
(通过删除计数器值的第二部分)对其进行再次排序,但是如果键的第一部分(文件大小
)相同(与计数器
值无关),则再次覆盖条目
这是我的密码:
TreeMap<String, String> fileNamesAndSizes = new TreeMap<String, String>(new Comparator<String>() {
public int compare(String o1, String o2) {
Long key1 = Long.valueOf(o1.split("#")[0]);
Long key2 = Long.valueOf(o2.split("#")[0]);
return key1.compareTo(key2);
}
});
TreeMap filenamesandsize=newtreemap(newcomparator()){
公共整数比较(字符串o1、字符串o2){
Long key1=Long.valueOf(o1.split(“#”)[0]);
Long key2=Long.valueOf(o2.split(“#”)[0]);
返回键1.compareTo(键2);
}
});
如何在myTreeMap
中获取唯一键而不覆盖现有值,并获得正确的(升序fileSize
)顺序
谢谢大家! 我会尝试将它们存储在这样的结构中:
TreeMap<Long, Set<String>> map; //Long file Size, Set <-- file name(s)
TreeMap地图//长文件大小,设置或
文件名
应为唯一键(Map
),或
(文件名、文件大小)
(Set
)李>
文件名
SortedMap filenamesandsize=newtreemap();
元组(文件名、文件大小)
class FileInfo实现了可比较的{
公共最终字符串名;
公共最终长尺寸;
公共文件信息(字符串名称,长){
this.name=名称;
这个。大小=大小;
}
@凌驾
公共整数比较(文件信息其他){
...
}
}
OrderedSet fileNamesAndSizes=新树集();
尝试使用值为list的映射,如下所示:
TreeMap<String, List<String>> map; // like <FileSize, List<FileName>>
TreeMap映射;//喜欢
上述操作将保持顺序,并将保存具有相同文件大小的文件名列表static int i=1;
static int i = 1 ;
TreeMap<String, String> fileNamesAndSizes = new TreeMap<String, String>(new Comparator<String>() {
public int compare(String o1, String o2) {
Long key1 = Long.valueOf(o1.split("#")[i]);
i += 1;
// somthing like this
return key1.compareTo(key2);
}
});
TreeMap filenamesandsize=newtreemap(newcomparator()){
公共整数比较(字符串o1、字符串o2){
Long key1=Long.valueOf(o1.split(“#”)[i]);
i+=1;
//像这样的事
返回键1.compareTo(键2);
}
});
比较器需要比较两个字段:
public int compare(String o1, String o2) {
String[] o1parts = o1.split("#");
String[] o2parts = o2.split("#");
long key1 = Long.parseLong(o1parts[0]);
long key2 = Long.parseLong(o2parts[0]);
int cmp = Long.compare(key1, key2);
if (cmp != 0)
return cmp;
return Long.compare(Long.parseLong(o1parts[1]), Long.parseLong(o2parts[1]));
}
存在各种更好的替代方案:
首先创建填充为零的字符串,然后使用字符串的自然顺序而不是自定义比较器
不要使用字符串,而是使用包含两个long的类,一个是大小,另一个是唯一的数字,或者使用包含大小和名称的类,并使用这两个字段适当地编写比较器
使用MultiSet(例如,来自Guava或Apache)
使用TreeSet
并将长度相等的文件名存储在一个集合中(这就是多集合通常在内部实现的方式)
您可以使用“fileSize+Filename”这样的复合键作为树映射键。这将解决所有问题。这也会导致问题,顺序不正确(文件大小的升序)rigth?No。这将由TreeMap本身处理。但是对于fileSize+fileName,我需要将键的数据类型更改为String。字符串的顺序不同于long/integers。您只将键设置为字符串,但顺序将基于整个复合键进行处理。将key设置为“1_file1”和“2_file2”,这将按树顶进行排序。或者您可以使用Guava的较短方式添加新文件:map.computeifassent(key,k->new HashSet()).add(set)代码>
class FileInfo implements Comparable<FileInfo> {
public final String name;
public final long size;
public FileInfo(String name, long size) {
this.name = name;
this.size = size;
}
@Override
public int compareTo(FileInfo other) {
...
}
}
OrderedSet<FileInfo> fileNamesAndSizes = new TreeSet<>();
TreeMap<String, List<String>> map; // like <FileSize, List<FileName>>
static int i = 1 ;
TreeMap<String, String> fileNamesAndSizes = new TreeMap<String, String>(new Comparator<String>() {
public int compare(String o1, String o2) {
Long key1 = Long.valueOf(o1.split("#")[i]);
i += 1;
// somthing like this
return key1.compareTo(key2);
}
});
public int compare(String o1, String o2) {
String[] o1parts = o1.split("#");
String[] o2parts = o2.split("#");
long key1 = Long.parseLong(o1parts[0]);
long key2 = Long.parseLong(o2parts[0]);
int cmp = Long.compare(key1, key2);
if (cmp != 0)
return cmp;
return Long.compare(Long.parseLong(o1parts[1]), Long.parseLong(o2parts[1]));
}