有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

仅当与阈值字节匹配时,java才会在映射中填充字符串值

我有一个tasks列表对象,我正在迭代该对象,并将每个任务对象附加到StringBuilder中,后跟新行,如下所示。现在,我将继续在同一个字符串生成器中追加任务对象,直到它达到60000字节的大小限制。一旦它达到极限,我将把这个字符串作为一个值填充到映射中,键将是带有增量索引的文件名。然后我将重置字符串生成器和其他东西,并再次重复此过程

因此,如果我有一个大的tasks对象,那么我将分割成多个字符串对象,其大小应始终小于60000字节

我得到了下面的代码,但我总是看到映射中的值的大小大于60000字节。我做错什么了吗?此外,我在两个不同的地方填充到HashMap,一个是达到限制,另一个是未达到限制

  public void populate(final List<Task> tasks) {
    Map<String, String> holder = new HashMap<>();
    int size = 0;
    int index = 0;
    StringBuilder sb = new StringBuilder();
    for (Task task : tasks) {
      sb.append(task).append(System.getProperty("line.separator"));
      size = sb.toString().getBytes(StandardCharsets.UTF_8).length;
      if (size > 60000) {
        String fileName = "tasks_info_" + index + ".txt";
        holder.put(fileName, sb.toString());
        index++;
        sb = new StringBuilder();
        size = 0;
      }
    }
    // for cases where we don't reach the limit
    if(sb.toString().length > 0) {
        String fileName = "tasks_info_" + index + ".txt";
        holder.put(fileName, sb.toString());        
    }
    System.out.println(holder);
  }

注意:如果每个任务对象超过60000 bytes,那么我将立即删除该对象并移动到下一个条目。但在现实中,这不会发生

更新:

public void populate(final List<Task> tasks, final long timestamp) {
    Map<String, String> holder = new HashMap<>();
    int size = 0;
    int index = 0;
    int nl = System.getProperty("line.separator").getBytes(StandardCharsets.UTF_8).length;
    StringBuilder sb = new StringBuilder();
    // new change
    sb.append(timestamp).append(System.getProperty("line.separator"));
    for (Task task : tasks) {
        int ts = String.valueOf(task).getBytes(StandardCharsets.UTF_8).length;
        if (size + ts + nl > 60000) {
            String fileName = "tasks_info_" + index + ".txt";
            holder.put(fileName, sb.toString());
            index++;
            sb = new StringBuilder();
            // new change
            sb.append(timestamp).append(System.getProperty("line.separator"));          
            size = 0;
        }
        sb.append(task).append(System.getProperty("line.separator"));
        size += ts + nl;
    }
    // for cases where we don't reach the limit
    if (size > 0) { // size can only be 0 if you have 0 tasks
        String fileName = "tasks_info_" + index + ".txt";
        holder.put(fileName, sb.toString());        
    }
    System.out.println(holder);
}

共 (3) 个答案

  1. # 1 楼答案

    其他答案已经提到了它不起作用的原因(你在它已经超过限制后添加)。但我认为,到目前为止,没有一个实现是正确的,这不仅仅是因为新行的大小被忽略了

    public Map<String, String> populate(final List<Task> tasks) {
        Map<String, String> holder = new HashMap<>();
        if (tasks.size() == 0)
            return holder;
        int index = 0;
        int nl = System.getProperty("line.separator").getBytes(StandardCharsets.UTF_8).length;
        StringBuilder sb = new StringBuilder();
        sb.append(System.currentTimeMillis()).append(System.getProperty("line.separator"));
        int size = sb.toString().getBytes(StandardCharsets.UTF_8).length;
        for (Task task : tasks) {
            int ts = String.valueOf(task).getBytes(StandardCharsets.UTF_8).length;
            if (size + ts + nl > 60000) {
                String fileName = "tasks_info_" + index + ".txt";
                holder.put(fileName, sb.toString());
                index++;
                sb = new StringBuilder();
                sb.append(System.currentTimeMillis()).append(System.getProperty("line.separator"));
                size = sb.toString().getBytes(StandardCharsets.UTF_8).length;
            }
            sb.append(task).append(System.getProperty("line.separator"));
            size += ts + nl;
        }
        String fileName = "tasks_info_" + index + ".txt";
        holder.put(fileName, sb.toString());        
        return holder;
    }
    
  2. # 2 楼答案

    我试过你的代码来确定答案。在向某人实际添加新任务的值之前,你需要尝试检查下一个大小。我修改了代码以反映这个解决方案。你能试试这个并告诉我们它是否对你有效吗

    public  void populate(final List<Task> tasks) {
            Map<String, String> holder = new HashMap<>();
            int size = 0;
            int index = 0;
            int lengthTask = 0;
            int lengthSb = 0;
            StringBuilder sb = new StringBuilder();
            for (Task task : tasks) {
                lengthTask = task.toString().getBytes(StandardCharsets.UTF_8).length;
                lengthSb = sb.toString().getBytes(StandardCharsets.UTF_8).length;
                if (size + lengthTask + lengthSb > 60000) {
                    System.out.println("last added size "+size);
                    String fileName = "tasks_info_" + index + ".txt";
                    holder.put(fileName, sb.toString());
                    index++;
                    sb = new StringBuilder();
                    size = 0;
                }
                sb.append(task).append(System.getProperty("line.separator"));
                size += sb.toString().getBytes(StandardCharsets.UTF_8).length;
                System.out.println("size "+size);
    
            }
            // for cases where we don't reach the limit
            String fileName = "tasks_info_" + index + ".txt";
            holder.put(fileName, sb.toString());
            System.out.println(holder);
        }
    
  3. # 3 楼答案

    如果我正确理解代码,我想应该是这样的

     size = sb.toString().getBytes(StandardCharsets.UTF_8).length;
    

    目前,它在字符串大小大于60000字节后插入映射,因此映射中的值大于60000字节

    if (size > 60000) {
        ...
        holder.put(fileName, sb.toString());
        ...
    }