仅当匹配阈值字节时才在映射中填充字符串值
Populate string value in a map only if matches the threshold bytes
我有一个 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);
}
如果我没看错代码,我猜应该是
size = sb.toString().getBytes(StandardCharsets.UTF_8).length;
而且目前是在字符串大于60000字节后插入映射,所以映射中的值已经超过60000字节
if (size > 60000) {
...
holder.put(fileName, sb.toString());
...
}
我试过你的代码来确定解决方案。在实际将新任务的值添加到 SB 之前,您需要尝试检查下一个大小。我修改了代码以反映此解决方案。你能试试这个并告诉我们它是否适合你吗?
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);
}
为什么不能用其他答案已经提到了(你在已经超过限制后添加)。但我认为到目前为止 none 的实现是正确的,不仅仅是因为换行符的大小被忽略了。
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;
}
我有一个 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);
}
如果我没看错代码,我猜应该是
size = sb.toString().getBytes(StandardCharsets.UTF_8).length;
而且目前是在字符串大于60000字节后插入映射,所以映射中的值已经超过60000字节
if (size > 60000) {
...
holder.put(fileName, sb.toString());
...
}
我试过你的代码来确定解决方案。在实际将新任务的值添加到 SB 之前,您需要尝试检查下一个大小。我修改了代码以反映此解决方案。你能试试这个并告诉我们它是否适合你吗?
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);
}
为什么不能用其他答案已经提到了(你在已经超过限制后添加)。但我认为到目前为止 none 的实现是正确的,不仅仅是因为换行符的大小被忽略了。
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;
}