【问题标题】:Better way to sort double Big Decimal numbers对双 Big Decimal 数字进行排序的更好方法
【发布时间】:2021-08-05 17:26:57
【问题描述】:

我有字符串列表,想要对值进行排序。

List<String> list = new ArrayList<String>();
list.add("200.1043725170");
list.add("100.1043725171");
list.add("100.1043725170");
list.add("65535.4294967295");
list.add("4294967295.65535");

尝试了几种方法来对相同的排序,但未能通过有效的解决方案来获得准确的结果。

list.forEach(value ->{
            dList.add(BigDecimal.valueOf(Double.parseDouble(value)));
        });
        Collections.sort(dList); 

使用上述方法,值是排序的,但最后一个零不在 (.) 之后打印,因为它不被认为是相关的。但我也需要有尾零,因为我们在其他地方比较这些值。

我正在寻找的最终输出是

100.1043725170
100.1043725171
200.1043725170
65535.4294967295
4294967295.65535

这里有什么建议可以通过有效的方法达到同样的效果

【问题讨论】:

  • 比较为字符串值。 dList 只是一个列表“List dList = new ArrayList();” -- 返回时,我必须从这个 API 中返回字符串列表
  • 什么是“双 BigDecimal 号码”?
  • 为什么你需要在第一个和第三个而不是最后一个填充零?
  • 在我的输入中,最后一个元素没有尾随零。我不应该操纵输入值只是想对它们进行排序。
  • 所以您需要在 9 位数字上使用单个填充零,但您不需要在 5 位数字上使用五个填充零?这是没有意义的。你说,«但我也需要有尾零,因为我们正在其他地方比较这些值。 »

标签: java sorting collections java-8


【解决方案1】:

更新

最好的解决方案是在Answer by Sergey Afinogenov,非常简短的一行代码。以下是我的两种方法。不是那么简洁,但我将把它们留在这里,因为它们可能会引起读者的兴趣。

避免double/Double

您的代码将您的字符串转换为doubleDouble 值。这样做会引入固有的inaccuracy of floating-point 技术。如果您关心准确性,请避免这样做。

相反,将您的输入字符串直接解析为BigDecimal 对象。

转换为BigDecimal后重新生成字符串

您必须将字符串直接解析为BigDecimal。将这些对象收集到一个列表中。种类。然后通过为每个BigDecimal 生成一个新的字符串值来生成一个新的String 对象的新列表。 Stack Overflow 上已经多次介绍了这些步骤中的每一个。搜索以了解更多信息。

NavigableMap&lt; BigDecimal , String &gt;

或者,使用SortedMap/NavigableMap。将从每个输入字符串派生的BigDecimal 映射到该字符串。键是BigDecimal 对象(即Comparable),按数学顺序自动排序。将调用 values 生成的集合提供给新的 List 的构造函数以获取结果。

List < String > list = List.of( "200.1043725170" , "100.1043725171" , "100.1043725170" , "65535.4294967295" , "4294967295.65535" );
NavigableMap < BigDecimal, String > map =
        list
                .stream()
                .collect(
                        Collectors.toMap(
                                ( String s ) -> new BigDecimal( s ) ,
                                Function.identity() ,
                                ( existing , replacement ) -> existing ,   // In case of duplicate key conflict, first one wins.
                                TreeMap :: new
                        )
                );
List < String > result = List.copyOf( map.values() );

System.out.println( result );

看到这个code run live at IdeOne.com

[100.1043725170, 100.1043725171, 200.1043725170, 65535.4294967295, 4294967295.65535]

【讨论】:

  • @Andy 同意。正如我所说,您有两个选择:重新创建字符串,或通过Map 管理它们。我好像没听懂你的意思?
  • @Basil Bourque 感谢版本和有趣的替代解决方案
  • 您可以将( String s ) -&gt; new BigDecimal( s ) 简化为BigDecimal::new。值得注意的是,这种toMap(…) 方法将消除重复,这与接受答案的list.sort(Comparator.comparing(BigDecimal::new)) 不同。要保留重复项(或可能不同的字符串,将解析为相同的值),您必须使用groupingBy 来获取每个键的所有字符串的列表,然后是流式传输和flatMaping 在@ 987654350@.
【解决方案2】:

您可以将列表保留为由每个 String 元素生成的按 BigDecimal 排序的字符串列表:

list.sort(Comparator.comparing(BigDecimal::new));

看到这个code run live at IdeOne.com

[100.1043725170, 100.1043725171, 200.1043725170, 65535.4294967295, 4294967295.65535]

【讨论】:

    猜你喜欢
    • 2011-07-22
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    相关资源
    最近更新 更多