java - 菜单树形结构

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)+"}";
  }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值