springenthusiast
springenthusiast

Reputation: 447

Construct XML element in parallel in java

I have a array of objects from which I am constructing an xml document using java like below -

Object[] arr = fetchData();
Document newDoc =DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element rootElement = newDoc.createElement("company");
for(int i=0;i<arr.length();i++)
{
    Element staff = new Element("staff");
    staff.setAttribute(new Attribute("id", i));
    staff.addContent(new Element("firstname").setText(arr[i].getFirstName()));
    staff.addContent(new Element("lastname").setText(arr[i].getLastName()));
    staff.addContent(new Element("nickname").setText(arr[i].getNickName()));
    staff.addContent(new Element("salary").setText(arr[i].getSalary()));
    ............
    ............
    ............
    ............
    ............
    rootElement.appendChild(staff);
}
newDoc.appendChild(rootElement);

The xml generated will be of following form -

<company>
  <staff id="1">
    <firstname>Foo</firstname>
    <lastname>Bar</lastname>
    <nickname>FB</nickname>
    <salary>999999</salary>
............
............
............
............
  </staff>
  ......
  ......
</company>

Above solution is working fine for small size of arrays but when array size increases it takes long time to process because of sequential processing of above code. Is there any way to process construction of staff element parallel either by using java 8 Stream parallel processing or threads in java?

Updated solution using CompletableFuture :

Object[] arr = fetchData();
Document newDoc =DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element rootElement = newDoc.createElement("company");
List<CompletableFuture<Element>> futureElements = new ArrayList<>();
for (int x = 0; x < arr.length(); x++) {
    Object e = arr[x];
    CompletableFuture<Element> f = CompletableFuture.supplyAsync(() -> getElement(newDoc, e));
    futureElements.add(f);
}

for (CompletableFuture<Element> e : futureElements)
        rootElement.appendChild(e.get());

newDoc.appendChild(rootElement); 

Upvotes: 1

Views: 508

Answers (1)

Ash
Ash

Reputation: 2602

What you could use is CompletableFutures

This way you could generate all the "staff" elements in a new thread then wait for them all to complete and add them

List<CompletableFuture<Element>> futureElements = new ArrayList<>()
for(int x = 0; x < arr.length; x++){
     //getElement(arr[x]) is the get staff element logic
     CompletableFuture<Element> f = CompletableFuture.supplyAsync(() -> getElement(arr[x]))
     futureElements.add(f);
}

CompletableFuture<Void> allOf = CompletableFuture.allOf(futureElements.toArray(new CompletableFuture[0]))

Now you can either modify the allOf CompletableFuture or you can use things like thenAccept() to create a new thread that will start as soon as all others complete, or do a .get() to join back to the main thread.

if you do a .get() then you can do something like

futureElements.forEach(f -> rootElement.append(f.get()));

Upvotes: 3

Related Questions