实时按值排序,自动舍弃,有界收集? [英] Real time sorted by value, auto-discarding, bounded collection ?

查看:117
本文介绍了实时按值排序,自动舍弃,有界收集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了一些时间尝试创建一个集合:

1)按值排序(不是按键)

2)每次添加元素时排序或修改

3)是固定大小,并根据排序方式自动排除最小/最大元素

4)是安全线程

I spent some time to try to make a collection that:
1) is sorted by value (not by key)
2) is sorted each time an element is added or modified
3) is fixed size and discard automatically smallest/biggest element depending of the sort way
4) is safe thread

所以3)和4)我认为这是相当确定。对于1)和2)这是一个有点更棘手。我花了很长时间在这个线程,尝试不同的示例,但一个大问题是,当对象插入时,集合只被排序一次。

So 3) and 4) I think it is quite ok. For 1) and 2) it was a bit more tricky. I spent quite a long time on this thread, experimenting the different sample, but one big issue is that the collection are sorted only once when object are inserted.

无论如何,我尝试实现我自己的集合,这是工作(不应该用于巨大的数据,因为它很频繁),但我不是那么高兴与设计。特别是在我的值对象被约束为可观察(这是好的),但不可比,所以我不得不使用脏的instanceof +异常为此。

Anyway, I try to implement my own collection, which is working (shouldn't be used for huge data as it is sorted quite often) but I'm not so happy with the design. Especially in the fact that my value objects are constrained to be Observable (which is good) but not comparable so I had to use a dirty instanceof + exception for this.

任何sugestion to improve this?

Any sugestion to improve this ?

这是代码:

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Observable;
    import java.util.Observer;

    public class SortedDiscardingSyncArray<K, V extends Observable> implements Observer {

        // Comparison way (ascendent or descendant)
        public static enum ComparisonWay
        {
            DESC,
            ASC;
        }

        // this is backed by a List (and ArrayList impl)
        private List<ArrayElement> array;

        // Capacity, configurable, over this limit, an item will be discarded
        private int MAX_CAPACITY = 200;

        // default is descending comparison
        private ComparisonWay compareWay = ComparisonWay.DESC;

        public SortedDiscardingSyncArray(ComparisonWay compareWay, int mAX_CAPACITY) {
            super();
            this.compareWay = compareWay;
            MAX_CAPACITY = mAX_CAPACITY;
            array = new ArrayList <ArrayElement>(MAX_CAPACITY);
        }

        public SortedDiscardingSyncArray(int mAX_CAPACITY) {
            super();
            MAX_CAPACITY = mAX_CAPACITY;
            array = new ArrayList<ArrayElement>(MAX_CAPACITY);
        }

        public SortedDiscardingSyncArray() {
            super();
            array = new ArrayList <ArrayElement>(MAX_CAPACITY);
        }

        public boolean put(K key, V value)
        {
            try {
                return put (new ArrayElement(key, value, this));
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            } 
            finally
            {
                sortArray();
            }

        }

        private synchronized boolean put(ArrayElement ae)
        {
            if (array.size() < MAX_CAPACITY)
            {
                return array.add(ae);
            }
            // check if last one is greater/smaller than current value to insert
            else if (ae.compareTo(array.get(MAX_CAPACITY-1)) < 0)
            {
                array.remove(MAX_CAPACITY - 1);
                return array.add(ae);
            }
            // else we don't insert
            return false;
        }

        public V getValue (int index)
        {
            return array.get(index).getValue();
        }

        public V getValue (K key)
        {
            for (ArrayElement ae : array)
            {
                if (ae.getKey().equals(key)) return ae.getValue();
            }
            return null;
        }

        public K getKey (int index)
        {
            return array.get(index).getKey();
        }

        private void sortArray()
        {
            Collections.sort(array);
        }

        public synchronized void setValue(K key, V newValue) {
            for (ArrayElement ae : array)
            {
                if (ae.getKey().equals(key)) 
                {
                    ae.setValue(newValue);
                    return;
                }
            }
        }
        public int size() {
            return array.size();
        }

        @Override
        public void update(java.util.Observable arg0, Object arg1) {
            sortArray();        
        }

        public static void main(String[] args) {

            //  some test on the class
            SortedDiscardingSyncArray<String, ObservableSample> myData = new SortedDiscardingSyncArray<String, ObservableSample>(ComparisonWay.DESC, 20);

            String Ka = "Ka";
            String Kb = "Kb";
            String Kc = "Kc";
            String Kd = "Kd";
            myData.put(Ka, new ObservableSample(0));
            myData.put(Kb, new ObservableSample(3));
            myData.put(Kc, new ObservableSample(1));
            myData.put(Kd, new ObservableSample(2));


            for (int i=0; i < myData.size(); i++)
            {
                System.out.println(myData.getKey(i).toString() + " - " + myData.getValue(i).toString());
            }
            System.out.println("Modifying data...");
            myData.getValue(Kb).setValue(12);
            myData.getValue(Ka).setValue(34);
            myData.getValue(Kd).setValue(9);
            myData.getValue(Kc).setValue(19);
            for (int i=0; i < myData.size(); i++)
            {
                System.out.println(myData.getKey(i).toString() + " - " + myData.getValue(i).toString());
            }
        }

        private class ArrayElement implements Comparable <ArrayElement> {

            public ArrayElement(K key, V value, Observer obs) throws Exception {
                super();
                // don't know how to handle that case
                // maybe multiple inheritance would have helped here ?
                if (! (value instanceof Comparable)) throw new Exception("Object must be 'Comparable'");
                this.key = key;
                this.value = value;
                value.addObserver(obs);
            }

            public String toString()
            {
                StringBuffer sb = new StringBuffer();
                sb.append(key);
                sb.append(" - ");
                sb.append(value);
                return sb.toString();
            }

            private K key;
            private V value;

            public K getKey() {
                return key;
            }

            public V getValue() {
                return value;
            }

            public synchronized void setValue(V value) {
                this.value = value;
            }

            @SuppressWarnings("unchecked")
            @Override
            public int compareTo(ArrayElement o) {

                int c;
                if (compareWay == ComparisonWay.DESC) c = ((Comparable<V>) o.getValue()).compareTo(this.getValue());
                else c = ((Comparable<V>) this.getValue()).compareTo(o.getValue());
                if (c != 0) {
                    return c;
                }
                Integer hashCode1 = o.getValue().hashCode();
                Integer hashCode2 = this.getValue().hashCode();
                // we don't check the compare way for hash code (useless ?)
                return hashCode1.compareTo(hashCode2);
            }

        }
    }

用于测试目的的其他类:

And the other class for testing purpose:

    import java.util.Observable;

    public class ObservableSample extends Observable implements Comparable <ObservableSample>
    {
        private Integer value = 0;

        public ObservableSample(int value) {
            this.value = value;
            setChanged();   
            notifyObservers();
        }

        public String toString()
        {
            return String.valueOf(this.value);
        }

        public void setValue(Integer value) {
            this.value = value;
            setChanged();   
            notifyObservers();
        }

        public Integer getValue() {
            return value;
        }

        @Override
        public int compareTo(ObservableSample o) {
            int c;
            c = (this.getValue()).compareTo(o.getValue());
            if (c != 0) {
                return c;
            }
            Integer hashCode1 = o.getValue().hashCode();
            Integer hashCode2 = this.getValue().hashCode();
            // we don't check the compare way for hash code (useless ?)
            return hashCode1.compareTo(hashCode2);
        }
    }


推荐答案

是一个版本更新。仍然不完全确定它是安全的线程,但findbugs工具没有给这么有用的提示。同样对于比较,我不想约束用户开发自己的比较器,我想保持简单的东西。

Here is a version updated. Still not completly sure it is safe thread but findbugs tool didn't give so usefull tips. Also for the comparisonWay, I don't want to constraint the user to develop its own comparator, I want to keep the things simple.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

public class SortedDiscardingSyncArray<K, V extends Observable & Comparable<V>> implements Observer {

    // Comparison way (ascendent or descendant)
    public static enum ComparisonWay { DESC, ASC; }

    // this is backed by a List (and ArrayList)
    private List<ArrayElement> array;

    // Capacity, configurable, over this limit, an item will be discarded
    private int maxCapacity = 200;

    // default is descending comparison
    private ComparisonWay compareWay = ComparisonWay.DESC;

    public SortedDiscardingSyncArray(ComparisonWay compareWay, int maxCapacity) {
        super();
        this.compareWay = compareWay;
        this.maxCapacity = maxCapacity;
        array = new ArrayList <ArrayElement>(maxCapacity);
    }

    public SortedDiscardingSyncArray(int maxCapacity) {
        super();
        this.maxCapacity = maxCapacity;
        array = new ArrayList<ArrayElement>(maxCapacity);
    }

    public SortedDiscardingSyncArray() {
        super();
        array = new ArrayList <ArrayElement>(maxCapacity);
    }

    // not synchronized, but calling internal sync put command
    public boolean put(K key, V value)
    {
        try {
            return put (new ArrayElement(key, value, this));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } 
        finally
        {
            sortArray();
        }
    }

    private synchronized boolean put(ArrayElement ae)
    {
        if (array.size() < maxCapacity) return array.add(ae);
        // check if last one is greater/smaller than current value to insert
        else if (ae.compareTo(array.get(maxCapacity-1)) < 0)
        {
            array.remove(maxCapacity - 1);
            return array.add(ae);
        }
        // else we don't insert and return false
        return false;
    }

    public V getValue (int index)
    {
        return array.get(index).getValue();
    }

    public V getValue (K key)
    {
        for (ArrayElement ae : array)
        {
            if (ae.getKey().equals(key)) return ae.getValue();
        }
        return null;
    }

    public K getKey (int index)
    {
        return array.get(index).getKey();
    }

    private synchronized void sortArray()
    {
        Collections.sort(array);
    }

    public synchronized void setValue(K key, V newValue) {
        for (ArrayElement ae : array)
        {
            if (ae.getKey().equals(key)) 
            {
                ae.setValue(newValue);
                return;
            }
        }
    }

    public int size() {
        return array.size();
    }

    @Override
    public void update(java.util.Observable arg0, Object arg1) {
        sortArray();        
    }

    public static void main(String[] args) {
        //  some test on the class
        SortedDiscardingSyncArray<String, ObservableSample> myData = new SortedDiscardingSyncArray<String, ObservableSample>(ComparisonWay.DESC, 20);

        String Ka = "Ka";
        String Kb = "Kb";
        String Kc = "Kc";
        String Kd = "Kd";
        myData.put(Ka, new ObservableSample(0));
        myData.put(Kb, new ObservableSample(3));
        myData.put(Kc, new ObservableSample(1));
        myData.put(Kd, new ObservableSample(2));


        for (int i=0; i < myData.size(); i++)
        {
            System.out.println(myData.getKey(i).toString() + " - " + myData.getValue(i).toString());
        }
        System.out.println("Modifying data...");
        myData.getValue(Kb).setValue(12);
        myData.getValue(Ka).setValue(34);
        myData.getValue(Kd).setValue(9);
        myData.getValue(Kc).setValue(19);
        for (int i=0; i < myData.size(); i++)
        {
            System.out.println(myData.getKey(i).toString() + " - " + myData.getValue(i).toString());
        }
    }

    private class ArrayElement implements Comparable <ArrayElement> {

        public ArrayElement(K key, V value, Observer obs) throws Exception {
            super();
            this.key = key;
            this.value = value;
            value.addObserver(obs);
        }

        public String toString()
        {
            StringBuffer sb = new StringBuffer();
            sb.append(key);
            sb.append(" - ");
            sb.append(value);
            return sb.toString();
        }

        private K key;
        private V value;

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        public synchronized void setValue(V value) {
            this.value = value;
        }

        @Override
        public int compareTo(ArrayElement o) {

            int c;
            if (compareWay == ComparisonWay.DESC) c = o.getValue().compareTo(this.getValue());
            else c = this.getValue().compareTo(o.getValue());
            if (c != 0) {
                return c;
            }
            Integer hashCode1 = o.getValue().hashCode();
            Integer hashCode2 = this.getValue().hashCode();
            // we don't check the compare way for hash code (useless ?)
            return hashCode1.compareTo(hashCode2);
        }

    }
}

这篇关于实时按值排序,自动舍弃,有界收集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆