【问题标题】:arraylist sort and convert to String[]arraylist 排序并转换为 String[]
【发布时间】:2018-02-23 11:34:49
【问题描述】:

我有一个自动生成的简单类,用于存储来自Retrofit 的响应。无论如何,在最后一步中,我想使用行内容,按位置从最高到最低对每个元素进行排序,排序后将其转换为 String[] 仅名称。我怎样才能以最有效的方式做到这一点?

public class RowModel implements Comparable<RowModel>{

    private String name;
    private double position;

    public double getPosition() {
        return position;
    }

    public void setPosition(float position) {
        this.position = position;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public RowModel(String name, double position) {
        this.name = name;
        this.position = position;
    }
}

我在网上搜索后发现这种方法可以执行排序,但我不确定结果是否正确。当然,我仍然不知道如何在最后一步将排序后的名称转换为String[]

@Override
public int compareTo(RowModel rowModel) {
    double comparePosition = ((RowModel) rowModel).getPosition();
    return (int) (this.position- comparePosition);
}

【问题讨论】:

  • 您可以使用Collections.sort( List&lt;RowModel&gt;... ) 进行排序,并且有不止一种方法可以获取String[] 的名称,其中之一是您可以创建一个字符串数组并遍历列表并填充数组it.next().getName()

标签: java arrays sorting arraylist


【解决方案1】:

您的 compareTo 方法在您比较双精度值时不起作用,并且当两个值的整数部分相同时它将失败(即比较 1.5 和 1.2 时,您的比较器将返回 0 但它应该返回 1)。

为此,您可以使用Double.compare(d1, d2)。您也不需要强制转换 rowModel。改变你的方法如下:

@Override
public int compareTo(RowModel rowModel) {
    double comparePosition = rowModel.getPosition();
    return Double.compare(this.position, comparePosition);
}

对于排序,您可以使用Collections.sort(rowModels)

要将此排序列表转换为名称列表,您可以使用 Stream API。

假设您有名为 rowModels 的 RowModel 排序列表。

List<String> names = rowModels.stream().map(RowModel::getName).collect(Collectors.toList());

如果要将此列表转换为数组,

String[] array = names.toArray(new String[names.size()]);

或直接,

String[] array = rowModels.stream().map(RowModel::getName).toArray(String[]::new);

【讨论】:

    【解决方案2】:

    假设在名为 rows 的变量中有一个行列表 RowModel,您可以使用 Stream API 轻松做到这一点:

    List<String> names = rows.stream().sorted()
                           .map(row -> row.getName())
                           .collect(Collectors.toList());
    

    中间步骤sorted() 确保根据RowModel 类中的Comparable 实现对流进行排序,在这种情况下。

    旁注:您的compareTo 实现可以改进,因为它可能会丢失精度(将double 转换为int 具有将两个对象视为equal 的副作用):

    @Override
    public int compareTo(RowModel rowModel) {
        double comparePosition = ((RowModel) rowModel).getPosition();
        double diff = this.position - comparePosition;
    
        return diff == 0 ? 0 : 
               (diff > 0 ? 1 : -1);
    }
    

    【讨论】:

    • 要比较双打,只需使用标准的static int Double.compare(double,double)
    【解决方案3】:
    List<RowModel> sortedModels = new ArrayList<>(models);
    Collections.sort(sortedModels);
    return sortedModels.toArray(new RowModel[0]);
    

    编辑: 要实际返回仅包含名称而不是整个 RowModels 的数组,您可以执行以下操作:

    String[] result = new String[sortedModels.size()];
    for (int i = 0; i < sortedModels.size(); i++) {
        result.[i] = sortedModels.get(i).getName();
    }
    

    使用 Java 8 流可能有一些更短的方法可以做到这一点,但我会把它留给实际使用它们的人。

    【讨论】:

    • 纯代码答案不好
    • sort 效果很好,但是如何只检索名称并将它们发送到 String[]?
    • 我不喜欢new RowModel[0]。你有长度,所以不要强制方法重新创建一个数组。从技术上讲,你已经有了一个大小正确的数组,所以我猜你可以使用它。
    • @AxelH 是的,那只是我懒惰。
    【解决方案4】:

    使用java.util.Collections类的util方法,即

    Collections.sort(list)
    

    如果你想对自定义对象进行排序,你可以使用

    Collections.sort(List<T> list, Comparator<? super T> c) 
    

    查看集合 api

    【讨论】:

      猜你喜欢
      • 2015-08-06
      • 2011-08-20
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 2012-08-31
      • 2017-11-09
      相关资源
      最近更新 更多