سؤال

لدي كائن يحدد "ترتيب الفرز الطبيعي" باستخدام <>. يتم تخزين هذه في الأشجار.

بخلاف إزالة الكائن وإعادة إضافته ، هل هناك طريقة أخرى لتحديث النوع عندما يتم تحديث الأعضاء الذين يتم استخدامهم لتحديد ترتيب الفرز؟

هل كانت مفيدة؟

المحلول

كما لاحظ آخرون ، لا توجد طريقة مدمجة. ولكن يمكنك دائمًا الفئة الفرعية التي تُدرج ، مع مُنشئك (مُنشئك) ، وإضافة الوظيفة المطلوبة:

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 متاحًا في الفصل.

Update 2012-08-07: الفصل متاح في القليل مستودع جيثب بما في ذلك إعادة صياغة تمهيدية مع رمز عينة تخطيطي وكذلك اختبارات الوحدة التي توضح كيف (لا) لاستخدامه بمزيد من التفصيل.

إذا كنت بحاجة حقًا إلى استخدام أ Set, ، ثم أنت محظوظ ، على ما أعتقد.

سأرمي بطاقة البرية ، على الرغم من ذلك - إذا كان وضعك مرنًا بما يكفي للعمل مع أ List بدل من Set, ، ثم يمكنك استخدام Collections.sort() لإعادة تورم List على الطلب. يجب أن يكون هذا أداءً ، إذا كان List لا يجب تغيير الطلب كثيرًا.

يساعد في معرفة ما إذا كانت الأشياء الخاصة بك ستتغير بزيادات صغيرة أو كبيرة. إذا كان كل تغيير صغيرًا جدًا ، فستبذل قصارى جهدك لوضع بياناتك في قائمة تحتفظ بها. للقيام بذلك ، عليك أن

  1. BinarySearch للعثور على فهرس العنصر
  2. تعديل العنصر
  3. في حين أن العنصر أكبر من جاره الجار ، فإنه تبديله مع جاره الجار
  4. أو إذا لم يحدث ذلك: في حين أن العنصر أقل من جاره اليسرى ، فإنه تبديله مع جاره اليسرى.

ولكن عليك أن تتأكد من أنه لا يمكن لأحد تغيير العنصر دون المرور "أنت" للقيام بذلك.

تعديل: ايضا! القوائم الزجاجية لديها بعض الدعم لهذا فقط:

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

بحثت عن هذه المشكلة عندما كنت أحاول تنفيذ جزء تمرير حركي يشبه مخطوطات Apple iPhone Wheel. العناصر في 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 قد يستغرق الأمر لحظة للالتزام بمهمة Runlater لمنصة Javafx ، وهذا هو السبب في أن الفهرس مدرج في فئة Wrapper هذه.

منذ scrollOffset يتم تغييره دائمًا بناءً على موضع التمرير للمستخدم على عجلة التمرير ، نحتاج إلى طريقة للتحديث. عادة ما يكون الترتيب هو نفسه دائمًا ، نظرًا لأن الإزاحة بالنسبة لموضع فهرس العنصر. لا يتغير الفهرس أبدًا ، لكن الإزاحة قد تكون سلبية أو إيجابية اعتمادًا على المسافة النسبية للعناصر من خاصية VValue الحالية أو خاصية HValue من ScrollPane.

للتحديث عند الطلب فقط عند الحاجة, ، ما عليك سوى اتباع إرشادات الإجابة أعلاه من قبل Tucuxi.

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

أين verticaloffsets هو TreeSet<ItemOffset>. إذا قمت بعمل طباعة من المجموعة في كل مرة يتم فيها استدعاء مقتطف التحديث هذا ، فسترى أنه يتم تحديثه.

بنيت فقط في الطريق هو إزالة وإعادة إضافة.

لا أعتقد أن هناك طريقة خارج الصندوق للقيام بذلك.

يمكنك استخدام نمط المراقب هذا يخطر Treeset كلما قمت بتغيير قيمة داخل عنصر ما ، ثم يزيلها وإعادة إدراجها.

وبهذه الطريقة ، يمكنك الاحتفاظ ضمنيًا بالقائمة المرتبة دون الاهتمام بالقيام بذلك باليد .. بالطبع سيحتاج هذا النهج إلى تمديده TreeSet عن طريق تعديل سلوك الإدراج (تحديد الميكانيكا المرصودة/الإخطار على العنصر المضافة فقط)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top