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);
}
});
如何在my
TreeMap
中获取唯一键而不覆盖现有值,并获得正确的(升序
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]));
        }