Правила:
- Каждая запись также имеет идентификатор как ROOT_ID.
- Если ROOT_ID записи соответствует идентификатору другой записи, она является дочерней по отношению к этой записи.
- Запись, ROOT_ID которой не совпадает ни с одним KEYID в списке является корневым (ROOT_ID может иметь значение null).
- Хотя я не готов поставить на это свою жизнь, вы можете предположить, что в коллекции сущностей есть только одна корневая запись (я проверил с аналитиком я могу обойтись без отображения последующих корней, если они есть).
Ваша цель — написать альтернативную реализацию метода fill() с лучшей временной сложностью. Старайтесь не делать код совершенно нечитаемым (мягкое требование).
Java 8, Apache Commons 2.6, Apache Collections 3.2.2.
import org.junit.jupiter.api.Test;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class TreeTest {
@Test
public void fill_givenModel_loadsBuildsAndLinksNodesInExpectedWay() {
DefaultTreeModel model = new DefaultTreeModel(null);
fill(model);
/*
I won't write space-intensive, time-consuming asserts,
but you can see if the model's correct in the debugger:
What I expect:
2
|_3
|_1
|_10
|_15
|_22
|_6
|_5
*/
} // set breakpoint here
void fill(DefaultTreeModel model) {
List nodes = buildNodes();
for (DefaultMutableTreeNode node : nodes) {
TreeEntity currentEntity = (TreeEntity) node.getUserObject();
Object currentKey = currentEntity.getId();
for (DefaultMutableTreeNode n : nodes) {
TreeEntity ce = (TreeEntity) n.getUserObject();
boolean isChild = areNumericallyEqual(ce.getRootId(), currentKey);
if (isChild) node.add(n);
}
}
findRoot(nodes).ifPresent(model::setRoot);
}
private List buildNodes() {
// imagine I actually load it from a DB
List entities = Arrays.asList(
new TreeEntity(6, 22),
new TreeEntity(1, 3),
new TreeEntity(3, 2),
new TreeEntity(2, 99),
new TreeEntity(22, 2),
new TreeEntity(5, 22),
new TreeEntity(10, 1),
new TreeEntity(15, 3)
);
return entities.stream()
.map(DefaultMutableTreeNode::new)
.collect(Collectors.toList());
}
private boolean areNumericallyEqual(Object firstValue, Object secondValue) {
// in the real scenario, it could be any type, so we have a similar utility method in our codebase
// except it does parsing in case the value is a string
Optional firstDoubleOptional = asDouble(firstValue);
Optional secondDoubleOptional = asDouble(secondValue);
return firstDoubleOptional.equals(secondDoubleOptional);
}
private static Optional asDouble(Object firstValue) {
Optional firstDoubleOptional = Optional.ofNullable(firstValue)
.filter(v -> v instanceof Number)
.map(Number.class::cast)
.map(Number::doubleValue);
return firstDoubleOptional;
}
private Optional findRoot(List nodes) {
return nodes.stream().filter(DefaultMutableTreeNode::isRoot).findFirst();
}
/**
* A simplistic entity with only essential fields.
*/
static class TreeEntity {
private final Integer id;
private final Integer rootId;
TreeEntity(Integer id, Integer rootId) {
this.id = id;
this.rootId = rootId;
}
public Integer getId() {
return id;
}
public Integer getRootId() {
return rootId;
}
@Override
public String toString() {
return String.valueOf(id);
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... tree-model
Мобильная версия