Any nice way to make a chain of immutable objects loop around?

眉间皱痕 提交于 2019-12-24 10:49:02

问题


This question is an extension of this question.

I have a class similar to the following.

 class HighlightableStructure {
      private final HighlightableStructure NEXT;  

      HighlightableStructure(HighlightableStructure next) {
           NEXT = next;
      }    
 }

where a HighlightableStructure points to the next structure to highlight.

Sometimes, these HighlightableStructures loop around and refer to a previous HighlightableStructure, but not the first in the chain. Something like h_1 -> h_2 ->h_3 -> ... -> h_n -> h_2, where h_i is an instance of HighlightableStructure.

Is there anyway I could construct something like this without reflection or losing immutability?


回答1:


One possible solution:

class HSequenceBuilder {
    private long id = 0;
    private final Map<Integer, H> map = new HashMap<Integer, H>();

    static H create(int next) {
        H h = new H(id, next, Collections.unmodifiableMap(map));
        map.put(id, h);
        id++;
        return h;
    }

    static H create() {
        create(id + 1);
    }

}

class H {
    private final id;
    private final Map<Integer, H> map;
    private final int next;

    H(int id, int next, Map<Integer, H> map) {
        this.id = id;
        this.next = next;
        this.map = map;
    }

    int getId() { return id; }
}
HSequenceBuilder builer = new HSequenceBuilder();
H h1 = builder.create(); // 1.
H h2 = builder.create(); // 2.
H h3 = builder.create(h2.getId()); // 3.



回答2:


The answer of the linked question is easily expandable to an arbitrary number of objects, if you have a way to specify the needed nodes at construction time, e.g.

final class CircularLinkedList<T> {
    final CircularLinkedList<T> next;
    final T value;

    public CircularLinkedList(T firstValue, List<T> other) {
        value = firstValue;
        next = other.isEmpty()? this: new CircularLinkedList<>(this, 0, other);

    }
    private CircularLinkedList(CircularLinkedList<T> head, int pos, List<T> values) {
        value = values.get(pos);
        next = ++pos == values.size()? head: new CircularLinkedList<>(head, pos, values);
    }

    @Override
    public String toString() {
        StringJoiner sj = new StringJoiner(", ").add(value.toString());
        for(CircularLinkedList<T> node = next; node != this; node = node.next)
            sj.add(node.value.toString());
        return sj.toString();
    }
}

Which you can use like

CircularLinkedList<String> cll
    = new CircularLinkedList<>("first", Arrays.asList("second", "third", "fourth"));
System.out.println(cll);

// demonstrate the wrap-around:
for(int i = 0; i < 10; i++, cll = cll.next) {
    System.out.print(cll.value+" .. ");
}
System.out.println(cll.value);



回答3:


You’ve got a linked list, which requires its nodes to be mutable. You can have mutable object but still get very similar benefits to immutability if you publish safe copies of your nodes.

Hide you nodes inside a containing object and when your API must return a node, return a copy of it instead, or even a copy of the entire structure as required.



来源:https://stackoverflow.com/questions/57137454/any-nice-way-to-make-a-chain-of-immutable-objects-loop-around

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!