Programing

객체가 값을 변경할 때 TreeSet 정렬 유지

lottogame 2020. 11. 6. 07:47
반응형

객체가 값을 변경할 때 TreeSet 정렬 유지


Comparable <>을 사용하여 '자연 정렬 순서'를 정의하는 개체가 있습니다. 이들은 TreeSet에 저장됩니다.

개체를 제거하고 다시 추가하는 것 외에 정렬 순서를 정의하는 데 사용되는 멤버가 업데이트 될 때 정렬을 업데이트하는 다른 방법이 있습니까?


다른 사람들이 지적했듯이 내장 방식은 없습니다. 그러나 언제든지 선택한 생성자로 해당 TreeSet을 하위 클래스 화하고 필요한 기능을 추가 할 수 있습니다.

public class UpdateableTreeSet<T extends Updateable> extends TreeSet<T> {

    // definition of updateable
    interface Updateable{ void update(Object value); }

    // constructors here
    ...

    // 'update' method; returns false if removal fails or duplicate after update
    public boolean update(T e, Object value) {
       if (remove(e)) {
           e.update(value);
           return add(e);
       } else { 
           return false;
       }
    }
}

그 이후부터는 ((UpdateableTreeSet)mySet).update(anElement, aValue)정렬 값과 정렬 자체를 업데이트 하기 위해 호출 해야합니다. 이렇게하려면 update()데이터 개체에 추가 메서드 를 구현해야 합니다.


나는 비슷한 문제가 있었고이 스레드와 tucuxi의 답변 (감사합니다!)을 발견했습니다 UpdateableTreeSet. 내 버전은

  • 그러한 세트를 반복하고,
  • 루프 내에서 (지연된) 요소 업데이트 / 제거 예약
  • 세트의 임시 복사본을 만들 필요없이 마지막으로
  • 루프가 끝난 후 모든 업데이트 / 제거를 일괄 작업으로 수행합니다.

UpdateableTreeSet사용자에게 많은 복잡성을 숨 깁니다. 지연된 대량 업데이트 / 제거 외에도 tucuxi에 표시된 단일 요소 업데이트 / 제거는 클래스에서 계속 사용할 수 있습니다.

2012-08-07 업데이트 :이 클래스는 회로도 샘플 코드가 포함 된 입문 README 와이 를 더 자세히 사용하는 방법을 보여주는 단위 테스트를 포함한 작은 GitHub 저장소 에서 사용할 수 있습니다.


를 정말로 사용해야한다면 Set운이 좋지 않은 것 같습니다.

그래도 와일드 카드를 사용하겠습니다. 상황이. List대신 으로 작업 할 수있을만큼 유연하다면 필요에 따라 다시 정렬하는 데 Set사용할 수 있습니다 . 순서를 많이 변경할 필요가 없다면 성능이 좋습니다 .Collections.sort()ListList


개체가 조금씩 변경되는지 또는 크게 변경되는지 알면 도움이됩니다. 각 변경 사항이 매우 적 으면 정렬 된 목록에 데이터를 넣는 것이 좋습니다. 이렇게하려면

  1. 요소의 인덱스를 찾기위한 binarySearch
  2. 요소 수정
  3. 요소가 오른쪽 이웃보다 크면 오른쪽 이웃과 교체하십시오.
  4. 또는 그렇지 않은 경우 : 요소가 왼쪽 이웃보다 작을 때 왼쪽 이웃과 교환하십시오.

그러나 "당신"을 거치지 않고는 아무도 요소를 변경할 수 없도록해야합니다.

편집 : 또한! Glazed Lists는 이에 대한 몇 가지 지원을 제공합니다.

http://publicobject.com/glazedlists/glazedlists-1.5.0/api/ca/odell/glazedlists/ObservableElementList.html


Apple iPhone 휠 스크롤과 유사한 키네틱 스크롤 창을 구현하려고 할 때이 문제를 찾았습니다. 의 항목 TreeSet은이 클래스입니다.

/**
 * Data object that contains a {@code DoubleExpression} bound to an item's
 * relative distance away from the current {@link ScrollPane#vvalueProperty()} or
 * {@link ScrollPane#hvalueProperty()}. Also contains the item index of the
 * scrollable content.
 */
private static final class ItemOffset implements Comparable<ItemOffset> {

    /**
     * Used for floor or ceiling searches into a navigable set. Used to find the
     * nearest {@code ItemOffset} to the current vValue or hValue of the scroll
     * pane using {@link NavigableSet#ceiling(Object)} or
     * {@link NavigableSet#floor(Object)}.
     */
    private static final ItemOffset ZERO = new ItemOffset(new SimpleDoubleProperty(0), -1);

    /**
     * The current offset of this item from the scroll vValue or hValue. This
     * offset is transformed into a real pixel length of the item distance from
     * the current scroll position.
     */
    private final DoubleExpression scrollOffset;

    /** The item index in the list of scrollable content. */
    private final int index;

    ItemOffset(DoubleExpression offset, int index) {
        this.scrollOffset = offset;
        this.index = index;
    }

    /** {@inheritDoc} */
    @Override
    public int compareTo(ItemOffset other) {
        double d1 = scrollOffset.get();
        double d2 = other.scrollOffset.get();

        if (d1 < d2) {
            return -1;
        }
        if (d1 > d2) {
            return 1;
        }

        // Double expression has yet to be bound
        // If we don't compare by index we will
        // have a lot of values ejected from the
        // navigable set since they will be equal.
        return Integer.compare(index, other.index);
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return index + "=" + String.format("%#.4f", scrollOffset.get());
    }
}

DoubleExpression인덱스가이 래퍼 클래스에 포함 된 이유는, 자바 FX 플랫폼의 runLater 작업에 바인딩 할 수있는 시간이 걸릴 수 있습니다.

Since the scrollOffset is always changing based on the user scroll position on the scroll wheel, we need a way to update. Usually the order is always the same, since the offset is relative to the item index position. The index never changes, but the offset could be negative or positive depending on the items relative distance from the current vValue or hValue property of the ScrollPane.

To update on demand only when needed, simply follow the guidance of the above answer by Tucuxi.

ItemOffset first = verticalOffsets.first();
verticalOffsets.remove(first);
verticalOffsets.add(first);

where verticalOffsets is a TreeSet<ItemOffset>. If you do a print out of the set each time this update snippet is called, you will see that it is updated.


Only built in way is to remove and re-add.


I don't think there is a out-of-the-box way to do it.

You could use an observer pattern that notifies the treeset whenever you change a value inside an element, then it removes and re-inserts it.

In this way you can implicitly keep the list sorted without caring of doing it by hand.. of course this approach will need to extend TreeSet by modifying the behaviour of insertion (setting the observed/notify mechanics on the just added item)

참고URL : https://stackoverflow.com/questions/2579679/maintaining-treeset-sort-as-object-changes-value

반응형