Android:AsyncTask.doInBackground中的可取消Java集合排序

Android:AsyncTask.doInBackground中的可取消Java集合排序,java,android,collections,android-asynctask,Java,Android,Collections,Android Asynctask,我正在为Android手机编写一个应用程序 我有一个java.util.ArrayList,其中包含需要自定义java.util.Comparator才能正确排序的对象 我知道我可以使用java.util.Collections.sort(),但由于数据量太大,我想在android.os.AsyncTask中对ArrayList进行排序 我不想使用多个AsyncTask对象来分别对数据的子集进行排序 任何异步任务都可以取消,因此我希望在排序时定期调用AsyncTask.isCancelled()

我正在为Android手机编写一个应用程序

我有一个
java.util.ArrayList
,其中包含需要自定义
java.util.Comparator
才能正确排序的对象

我知道我可以使用
java.util.Collections.sort()
,但由于数据量太大,我想在
android.os.AsyncTask
中对
ArrayList
进行排序

我不想使用多个AsyncTask对象来分别对数据的子集进行排序

任何异步任务都可以取消,因此我希望在排序时定期调用
AsyncTask.isCancelled()
。如果返回true,我将放弃排序(以及整个数据集)

我在谷歌上搜索了一下,但在定期检查取消情况时,找不到一种方便排序的方法

在我的
java.util.Comparator.compare()
实现中,我可能能够调用
isCancelled()
,并在返回true时抛出我自己的
java.lang.RuntimeException
子类。然后
尝试{java.util.Collections.sort(ArrayList,Comparator);}catch(){}
获取该特定异常。我对这种方法感到不太舒服

或者,我可以使用中介
java.util.TreeSet
并编写两个循环,每个循环在每次迭代之前检查取消。第一个循环将
ArrayList
的所有项添加到
TreeSet
(我的
Comparator
实现在插入时保持它们的排序)。由于
TreeSet
natural
java.util.Iterator
,第二个循环将以正确的顺序将
TreeSet
中的所有对象添加回
ArrayList
。这种方法使用了一些额外的内存,但肯定会起作用

我能想到的最后一种方法是实现我在Android中一直在寻找的东西:使用
java.util.Comparator
和定期检查取消的
Android.os.AsyncTask
进行通用
java.util.List
(最好是快速)排序

有人发现了吗?
对于这个问题,你还有别的解决办法吗

编辑:


虽然我没有考虑过排序方法签名会是什么样子,但我也非常乐意使用
android.os.CancellationSignal
来决定何时放弃排序。

我将尝试在这里描述我的思考过程。如果任何人在任何时候都有更好的报价

让我们再次确认我们在这里努力实现的目标。 我们需要一个具有以下属性的排序算法

  • 在单个任务上运行

  • 到位,即不使用额外内存

  • 我们应该能够随意取消排序,即当我们决定不再需要排序时,立即返回或非常接近排序

  • 有效率

  • 不会使用异常来控制完全正常的应用程序流。你对那件事感到不舒服是对的☺

    没有本地的android工具可以做到这一点

  • 让我们关注一下需求3

    这是一段关于取消任务的引用

    大宗报价 为确保尽快取消任务,应始终定期从doInBackground(对象[])检查isCancelled()的返回值,如果可能的话(例如在循环内)

    也就是说,是一种迭代排序算法,在每次迭代中,必须检查isCancalled()值flag将满足这一要求。问题是简单的迭代排序算法,如插入排序,通常效率不高。对于小的输入来说,这应该不太重要,但既然您说您的典型输入是一个巨大的数组列表,这触发了我们的搜索,我们需要尽可能保持效率

    既然你提到了快速排序,我在想,它已经得到了我们所需要的一切!它高效,到位,只运行一个任务。只有一个不足。它是递归的,以它的经典形式,这意味着它不会在取消后立即返回。幸运的是,一个简短的谷歌搜索可以产生许多结果,包括。简言之,您可以找到一种迭代的快速排序变体。这是通过将递归调用堆栈替换为存储递归实现用于执行“分区”的相同索引的堆栈来实现的。
    采用这种算法,在每次迭代中添加一个检查asyncTask.isCancelled()的方法,您就可以得到一个满足所有要求的解决方案。

    或者您可以运行一个单独的线程来检查isCancelled(),这样做的目的是,当isCancelled返回true时,只需使您的排序类或方法终止。如果任务被取消,我将投票支持从comparator中抛出RuntimeException。这可能看起来像是一个小技巧,但考虑到这种情况,它比必须滚动您自己的排序代码更优雅。