【问题标题】:Android Joda Time, Having trouble sorting strings from ISOPeriodFormatAndroid Joda Time,从 ISOPeriodFormat 排序字符串时遇到问题
【发布时间】:2016-06-20 05:41:10
【问题描述】:

我一直在到处寻找解决方案,但无法找到可行的解决方案。

我有一个“记分牌”,需要显示应用使用 Joda Time 计算的最高“时间”(两个瞬间之间的时间段)。

所有字符串都存储在一个 ArrayList 中,并通过 ArrayAdapter 和 ListView 显示。

问题:即使使用 ISO 格式,Collections.sort 似乎也无法正常工作。

我正在使用以下格式节省时间:

PeriodFormatter formatter = ISOPeriodFormat.standard();

它给出了这个:“PT1M15.664S” (1 分 15 秒)

我将其转换为字符串并存储到 ArrayList 中。

如何对这些字符串进行排序,使其在记分板上的时间从最长到最短?

我尝试过自然排序和 Alphanum Comparator,但没有成功。每次超过上限(分钟、小时、天)时,值都会变成这样:

"PT2.455S"
"PT1.324S"
"PT1M15.333S"

而不是我想要的:

"PT1M15.333S"
"PT2.455S"
"PT1.324S"

使用 Collection.sort(myArrayList) 也不起作用。

知道我应该怎么做吗?

我的代码:

 // set is a set<String> retrieving it's values from a stringset scores saved
in the sharedpreferences of the app

 set = sharedPreferences.getStringSet("scores", null);

 //scores is the ArrayList
 scores.clear();


  if (set != null){

      scores.addAll(set);

  }else{

      scores.add("No Time Yet!");
      set = new LinkedHashSet<String>();
      set.addAll(scores);
      sharedPreferences.edit().putStringSet("scores",set).apply();
  }

//removing the String No Time Yet because it no longer serves a purpose here
  if ((set != null)&& (set.size()>1)){
      scores.remove("No Time Yet!");
  }


    arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,scores);

listView.setAdapter(arrayAdapter);

Collections.sort(scores);

感谢您的宝贵时间。

【问题讨论】:

  • 想法:不要对字符串值进行排序。 将 Joda 句点转换为字符串之前对它们进行排序。
  • 当然,您首先必须定义排序顺序,例如P30DT2H 是大于还是小于 P1MPT23H30M 是大于还是小于 P1D?如果您正在观察夏令时,答案是 less,除了一年中的某一天,它是 more。同样,PT24HP1D 是相等的,除了每年 2 天。
  • 这将是一个好主意,但我无法将句点保存为 android 中 sharedpreferences 的一部分(我从另一个活动中获取值),所以我坚持使用字符串集.
  • 然后将它们解析回句点。

标签: java android sorting arraylist jodatime


【解决方案1】:

简答:使用类Duration,而不是Period

说明:

您使用Period 类的一般方法是错误的。这种类型表示各种数量单位对的元组。其中一些是不可兑换或不可比较的。例如,不可能确定 P30D 是否大于或等于或小于 P1M(想想 2 月、4 月或 8 月)。所以很清楚为什么你不能按句点排序。为什么这个类没有实现接口Comparable。这个反对意见对于Period 类型的对象以及它的规范ISO 表示(作为字符串)是有效的。

但是既然你想要

最高的“时间”(两个瞬间之间的时间段)

您可以使用Duration 来确定两个给定时刻之间经过的秒数和毫秒数的绝对值。这种类型具有可比性,只有两个对您来说可能并不重要的小约束:

  • 精度限制为毫秒
  • 忽略闰秒

我建议比较持续时间对象,而不是字符串,因为您需要的是时间顺序,而不是字典顺序。因此,您可以使用Duration(如 PT72.345S)的字符串表示形式进行存储,但对其进行解析以进行比较:

Instant i1 = new Instant(0);
Instant i2 = new Instant(72_345);
Duration d1 = new Duration(i1, i2);

Instant i3 = new Instant(60_000);
Instant i4 = new Instant(200_710);
Duration d2 = new Duration(i3, i4);

List<String> scoreTimes = new ArrayList<>();
scoreTimes.add(d1.toString());
scoreTimes.add(d2.toString());

// order from longest times to shortest times
Collections.sort(
    scoreTimes,
    new Comparator<String>() {

        @Override
        public int compare(String s1, String s2) {
            return Duration.parse(s2).compareTo(Duration.parse(s1));
        }
    }
);

System.out.println(scoreTimes); // [PT140.710S, PT72.345S]

【讨论】:

  • 非常感谢你解释得这么好。我现在明白为什么我所做的没有奏效。我按照您的示例进行操作,一切正常!
猜你喜欢
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
  • 2017-02-09
相关资源
最近更新 更多