Perlin Noise生成地图保存坐标至JSON仅存约50个?setJSONObject疑问
问题根因与修复方案
为什么最终JSON只写入最后约50个坐标
- 出现这类内容丢失的核心原因基本可以锁定为两个常见的代码逻辑错误,叠加后刚好会出现“前面生成的全没了,只剩最后小半截”的现象:
- 第一类错误:JSON存储结构的初始化位置写在了坐标生成的循环内部。每生成一个坐标就重新新建一个空的JSONArray/JSONObject,上一轮循环写入的内容会直接被新的空结构覆盖,循环全程不会保留之前的累计值,跑完自然只剩最后几轮生成的内容。
- 第二类错误:把
JSONArray的set()方法当成追加元素的方法使用,逐坐标传入循环变量作为下标覆盖内容。这个方法本身不会自动扩容数组、也不会追加新元素,只会替换数组里已有下标的值,当数组长度被撑到你循环的最终值时,前面循环写入的所有旧内容会被后面的值挨个替换掉,最后只剩最后一批替换操作留下的坐标。
- 额外排查项:如果文件写入逻辑是在循环内部逐次调用,且打开文件的模式为覆盖写入而非追加,循环最后一次执行的写入操作会把之前所有写入的文件内容全部清空,最终文件里也只会留下最后一次写入的内容。
为什么setJSONObject需要把i作为第一个参数
- 你从文档里复制的带
i参数的写法,本质是调用了JSONArray.set(int index, Object value)的方法,这个方法的设计逻辑根本不是用来新增元素的:- 第一个参数
i代表的是要被替换的元素在数组中的索引位置,方法的完整作用是:找到数组中下标为i的位置,把该位置原本存储的内容替换成你传入的JSON对象。 - 这个方法的运行前提是数组已经存在长度大于
i的预置元素,否则会直接抛出数组下标越界异常。你能正常运行完没有报错,说明之前的循环逻辑已经把数组长度填充到了循环的最终值,所有set操作只是在已存在的数组槽位上反复做内容替换,完全没有起到累加存储所有坐标的作用。
- 第一个参数
- 真正用于向JSONArray追加新元素的方法是
put(Object value),这个方法会自动将新元素追加到数组末尾,不需要手动传入下标参数。
修复后的核心逻辑参考:
// 循环外部初始化全局JSON存储结构 JSONObject rootMap = new JSONObject(); JSONArray allCoordinates = new JSONArray(); // 循环内逐次生成坐标并追加 for (int pointIndex = 0; pointIndex < totalGenerateCount; pointIndex++) { // 调用Perlin Noise生成单个坐标点 float[] point = perlinNoise.getPoint(pointIndex); // 构造单条坐标的JSON对象 JSONObject pointEntry = new JSONObject(); pointEntry.put("x", point[0]); pointEntry.put("y", point[1]); pointEntry.put("height", point[2]); // 用put方法追加到数组,禁止用set allCoordinates.put(pointEntry); } // 所有坐标生成完毕后,一次性写入文件 rootMap.put("coordinateList", allCoordinates); Files.writeString(Path.of("perlin_map.json"), rootMap.toString(2));
内容的提问来源于stack exchange,提问作者T888
相关产品推荐
相关产品推荐

