1、结构一
限制:(数据库添加数据的时候,进行限制最好;id 与 pid 为 int)
不要出现类似下面的情况,即 B = C && D > B,
换句话说,先 sort(pid) 再 sort(id) 之后,某一项的 pid 对应的 id应该在该项前面,即 A = D && B < D
menuList.add(new Menu(112, 116, "name1011", "url1011"));
menuList.add(new Menu(116, 119, "name1011", "url1011"));
//------------------------------------------------------
menuList.add(new Menu(A, B, "name1011", "url1011"));
menuList.add(new Menu(C, D, "name1011", "url1011"));
代码实现
public class Client {
final static List<Menu> menuList = new ArrayList<>();
static {
menuList.add(new Menu(2, 0, "name1", "url1"));
menuList.add(new Menu(8, 1, "name7", "url7"));
menuList.add(new Menu(7, 3, "name8", "url8"));
menuList.add(new Menu(4, 1, "name2", "url2"));
menuList.add(new Menu(5, 6, "name4", "url4"));
menuList.add(new Menu(3, 2, "name9", "url9"));
menuList.add(new Menu(1, 0, "name3", "url3"));
menuList.add(new Menu(6, 2, "name5", "url5"));
menuList.add(new Menu(111, -1, "name1011", "url1011"));
menuList.add(new Menu(9, 7, "name10", "url10"));
menuList.add(new Menu(0, -1, "name6", "url6"));
menuList.add(new Menu(119, 111, "name1011", "url1011"));
//menuList.add(new Menu(112, 116, "name1011", "url1011")); //wrong
//menuList.add(new Menu(116, 119, "name1011", "url1011")); //wrong
}
public static void main(String[] args) {
Collections.sort(menuList);
Tree tree = new Tree();
menuList.forEach(new Consumer<Menu>() {
@Override
public void accept(Menu m) {
Node node = new Node(m);
tree.add(node);
}
});
System.out.println(tree);
}
}
abstract class NodeObject implements Comparable<NodeObject> {
protected int id;
protected int pid;
public NodeObject(int id, int pid) {
this.id = id;
this.pid = pid;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
@Override
public int compareTo(NodeObject o) {
int pidSort = this.pid - o.pid;
return pidSort == 0 ? this.id - o.id : pidSort;
}
}
class Menu extends NodeObject {
private String name;
private String url;
public Menu(int id, int pid, String name, String url) {
super(id, pid);
this.name = name;
this.url = url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "{\"id\":" + id + ",\"pid\":" + pid + ",\"name\":\"" + name + "\",\"url\":\"" + url + "\"}";
}
}
class Tree extends AbstractList<Node> {
private List<Node> list;
private int searchCount;
public Tree() {
list = new ArrayList<>();
}
@Override
public boolean add(Node node) {
searchCount = 0;
if (list.size() == 0) {
modCount++;
list.add(node);
} else {
list.forEach(new Consumer<Node>() {
@Override
public void accept(Node n) {
search(n, node);
}
});
}
if(modCount == searchCount){
modCount++;
list.add(node);
}
return true;
}
public void search(Node node, Node target) {
Objects.requireNonNull(node);
searchCount ++;
if (node.getData().getId() == target.getData().getPid()) {
modCount++;
node.addNext(target);
target.setPrev(node);
} else {
Node[] nexts = node.getNexts();
for (Node n : nexts) {
if (n != null) {
search(n, target);
}
}
}
}
@Override
public Node get(int index) {
return list.get(index);
}
@Override
public int size() {
return list.size();
}
@Override
public String toString() {
return list.toString();
}
}
class Node {
private static final int DEFAULT_CAPACITY = 10;
protected transient int size = 0;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private static final Node[] EMPTY_NEXTS = {};
private Node prev;
private Node[] nexts;
private NodeObject data;
public Node(NodeObject data) {
this.data = data;
this.nexts = EMPTY_NEXTS;
}
public Node(NodeObject data, int minCapacity) {
this.data = data;
this.nexts = new Node[minCapacity];
}
public Node[] addNext(Node node) {
ensureCapacityInternal(size + 1);
nexts[size++] = node;
node.prev = this;
return nexts;
}
private void ensureCapacityInternal(int minCapacity) {
if (nexts == EMPTY_NEXTS) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
if (minCapacity - nexts.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = nexts.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
nexts = Arrays.copyOf(nexts, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
public Node[] sortNext() {
Arrays.sort(nexts);
return nexts;
}
public Node[] sortNext(Comparator<Node> comparator) {
Arrays.sort(nexts, comparator);
return nexts;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
public Node[] getNexts() {
return nexts;
}
public NodeObject getData() {
return data;
}
public void setData(NodeObject data) {
this.data = data;
}
@Override
public String toString() {
return "{\"data\":"+data+",\"nexts\":"+Arrays.asList(nexts)+"}";
}
}