我一直在尝试创建一个带有大量文档的Json字符串,但是使用下面的代码但是我超出了范围或者必须等到5分钟b4字符串被大肆宣传如何优化代码?
public String getJson() throws NotesException {
...
View view1 = ...;
ViewNavigator nav =view1.createViewNav();
ViewEntry ve = nav.getFirst();
JSONObject jsonMain = new JSONObject();
JSONArray items = new JSONArray();
Document docRoot = null
while (ve != null) {
docRoot= ve.getDocument();
items.add(getJsonDocAndChildren(docRoot));
ViewEntry veTemp = nav.getNextSibling(ve);
ve.recycle();
ve = docTemp;
}
jsonMain.put("identifier", "name");
jsonMain.put("label", "name");
jsonMain.put("items", items);
return jsonMain.toJSONString();
}
private JSONObject getJsonDocAndChildren(Document doc) throws NotesException {
String name = doc.getItemValueString("Name");
JSONObject jsonDoc = new JSONObject();
jsonDoc.put("name", name);
jsonDoc.put("field", doc.getItemValueString("field"));
DocumentCollection responses = doc.getResponses();
JSONArray children = new JSONArray();
getDocEntry(name,children);//this add all doc that has the fieldwith the same value name to children
if (responses.getCount() > 0) {
Document docResponse = responses.getFirstDocument();
while (docResponse != null) {
children.add(getJsonDocAndChildren(docResponse));
Document docTemp = responses.getNextDocument(docResponse);
docResponse.recycle();
docResponse = docTemp;
}
}
jsonDoc.put("children", children);
return jsonDoc;
}
答案 0 :(得分:1)
这里有一些东西,从一般效率到基于你想要如何使用代码的优化。
可能加速处理的最大问题是只进行查看操作,而不会破解文档。由于您希望不加选择地获得响应,因此可以将响应文档添加到原始视图中,并打开“在层次结构中显示响应”选项。然后,如果您在视图中有Name
和field
列(并且没有“仅显示回复”)列,那么沿着视图向下走nav.getNext()
将依次获取它们。通过存储每个先前条目的entry.getIndentLevel()
值并在循环开始时进行比较,您可以在JSON树上“上下”:当缩进级别增加1时,创建一个新数组并添加它对现有的对象;当它减少时,加强一个。一开始它可能有点概念上的尴尬,不得不在平坦循环中跟踪先前的状态,但它会更有效率。
另一个选项,也是不必破解每个单独文档的好处,是查看按@Text($REF)
分类的响应文档,然后使您的递归方法看起来更像:
public static void walkTree(final View treeView, final String documentId) {
ViewNavigator nav = treeView.createViewNavFromCategory(documentId);
nav.setBufferMaxEntries(400);
for (ViewEntry entry : nav) {
// Do code here
walkTree(treeView, entry.getUniversalID(), callback);
}
}
(该示例使用OpenNTF Domino API,但是,如果您不使用它,则可以将for循环下转换为传统样式)
作为一个小改进,只要您遍历ViewNavigators,就可以设置view.setAutoUpdate(false)
然后nav.setBufferMaxEntries(400)
来改进内部缓存。
最后,根据您的需求 - 例如,如果您将JSON直接输出到HTTP响应的输出流 - 您可以使用JsonWriter
代替JsonObject
来流式传输内容而不是在内存中构建一个巨大的对象。我在这里用一些简单的代码写了它:https://frostillic.us/blog/posts/EF0B875453B3CFC285257D570072F78F
答案 1 :(得分:1)
您应首先确定代码中花费的时间。也许它在doc.getResponses()
或responses.getNextDocument()
中,您没有在此处显示。
可以在您的代码段中进行的明显优化如下:
基本上你有一些名为Document的数据结构,并构建一个由JSONObjects和JSONArrays组成的内存JSON结构。然后将此JSON结构序列化为String并返回。
您可以直接使用JsonWriter而不是构建JSON结构(不知道您正在使用什么JSON库,但必须有类似JsonWriter的东西)。这避免了临时JSON结构的内存分配。
在getJson()
开始:
StringWriter stringOut = new StringWriter();
JsonWriter out = new JsonWriter(stringOut);
并结束
return stringOut.toString();
现在,无论您在哪里创建JSONObjects或JSONArrays,都可以调用相应的编写器方法。 e.g。
private void getJsonDocAndChildren(Document doc, JsonWriter out) throws NotesException {
out.name("name");
out.value(doc.getItemValueString("Name"));
out.name("field");
out.value(doc.getItemValueString("field"));
DocumentCollection responses = doc.getResponses();
if (responses.getCount() > 0) {
Document docResponse = responses.getFirstDocument();
out.startArray();
...
希望你明白这一点。