【问题标题】:Sort arraylist in specific order [duplicate]按特定顺序对arraylist进行排序[重复]
【发布时间】:2015-05-06 08:41:05
【问题描述】:

我有一个如下的数组列表:

ArrayList<PhoneNumber> arrayListToSort 

PhoneNumber 具有以下属性

private String number;

private String numberType;

数字类型如 MOBILE , HOME , OFFICE

我想按numberTypearrayListToSort 进行排序。

我可以用简单的字母顺序来做到这一点。

但我的问题是如何按以下顺序对列表进行排序。

  1. 手机
  2. 首页
  3. 办公室

【问题讨论】:

  • number 应该是一个枚举。排序会更容易。
  • @TomJonckheere 这是另一个问题。
  • @SashaSalauyou 确实...感谢您的注意!我更新了。
  • 为什么这是另一个问题?为什么不能为它创建Comparator
  • @TomJonckheere 还有一个... OP 没有可以按自然顺序排序的属性,他们需要以某种方式定义此顺序。

标签: java sorting arraylist


【解决方案1】:

你可以试试 PhonNumberType with enum 检查下面的代码

 package test;

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

enum PhonNumberType {
    MOBILE, HOME, OFFICE
}

class PhoneNumber implements Comparable<PhoneNumber> {
    private String number;
    private PhonNumberType phonNumberType;

    @Override
    public int compareTo(PhoneNumber o) {
        return this.phonNumberType.compareTo(o.phonNumberType);
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public PhonNumberType getNumberType() {
        return phonNumberType;
    }

    public void setNumberType(PhonNumberType phonNumberType) {
        this.phonNumberType = phonNumberType;
    }


    @Override
    public String toString() {
        return "PhoneNumber [number=" + number + ", phonNumberType=" + phonNumberType + "]";
    }

}

public class T {

    public static void main(String[] args) {
        List<PhoneNumber> test = new ArrayList<PhoneNumber>();
        PhoneNumber pn = new PhoneNumber();
        pn.setNumber("1");
        pn.setNumberType(PhonNumberType.HOME);

        test.add(pn);

        pn = new PhoneNumber();
        pn.setNumber("2");
        pn.setNumberType(PhonNumberType.MOBILE);
        test.add(pn);

        pn = new PhoneNumber();
        pn.setNumber("3");
        pn.setNumberType(PhonNumberType.OFFICE);
        test.add(pn);

        Collections.sort(test);

        System.out.println(test);
    }

}

输出为:[PhoneNumber [number=2, phonNumberType=MOBILE], PhoneNumber [number=1, phonNumberType=HOME], PhoneNumber [number=3, phonNumberType=OFFICE]]

【讨论】:

    【解决方案2】:

    您的排名不是自然顺序。

    要获得目标结果,您必须定义自己的比较器。

    顺便说一句,正如@Alexis C. 所说,为您的 numberType 使用枚举

    【讨论】:

    • 答案正文丢失。
    【解决方案3】:

    为此使用枚举:

    public enum NumberType {
        MOBILE,HOME,OFFICE;
    }
    

    如果您的电话号码具有可比性:

    @Override
    public int compareTo(PhoneNumber o) {
        return numberType.compareTo(o.numberType);
    }
    

    它将遵循枚举中描述的顺序:

    MOBILE,HOME,OFFICE
    

    【讨论】:

    • 最好在 Collections.sort 中使用自定义比较器
    【解决方案4】:
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class Main {
        public static void arrayListToSort(ArrayList<PhoneNumber> arrayListToSort) {
            Map<String, Integer> phoneTypeToOrder = new HashMap<>();
            phoneTypeToOrder.put("MOBILE", 0); 
            phoneTypeToOrder.put("HOME", 1);
            phoneTypeToOrder.put("OFFICE", 2);
    
            Collections.sort(arrayListToSort, new Comparator<PhoneNumber>() {
    
                @Override
                public int compare(PhoneNumber o1, PhoneNumber o2) {
                    if (o1 == null || o1.numberType == null) {
                        return -1;
                    }
                    if (o2 == null || o2.numberType == null) {
                        return 1;
                    }
                    Integer o1Order = phoneTypeToOrder.get(o1.numberType);
                    Integer o2Order = phoneTypeToOrder.get(o2.numberType);
                    return o1Order.compareTo(o2Order);
                }
    
            });
        }
    }
    
    class PhoneNumber {
        String number;
    
        String numberType;
    }
    

    【讨论】:

      【解决方案5】:

      我建议使用名为 Comparator 的自定义“排序方法”。在此比较器中,您为每个将在运行时计算的记录定义一个“值”。这个值的计算完全取决于你。例如,您可以定义“foo”== 1、“bar”== 2 和“john”== 654。Java 的排序方法将询问每条记录的“值”并进行相应排序(我认为使用 Quicksort -算法,但我不确定)。

      这里有一个很好的小教程,可以让您进入这个主题,并展示如何正确实现 Comparator 和 Comparable-Interfaces: http://www.tutorialspoint.com/java/java_using_comparator.htm

      这个更深入一点:http://www.journaldev.com/780/java-comparable-and-comparator-example-to-sort-objects

      此外:如前所述,使用枚举作为数字类型。不是因为它更容易(恕我直言),而是因为比较枚举比比较字符串要快得多。

      【讨论】:

        【解决方案6】:

        您可以使用 TreeSet 集合,对条目进行排序。

        TreeSet<PhoneNumber> sortedList = new TreeSet<>((PhoneNumber p1, PhoneNumber p2) -> p1.compareTo(p2));
        

        由于您必须为条目定义顺序,您的 PhoneNumber 类将必须实现 Comparable 接口,并且您需要重写 compareTo() 方法以说明您将在 numberType 上进行比较

        public int compareTo(Object o) {
            PhoneNumber p = (PhoneNumber) o;
            return numberType.equals(o.getNumberType())?0:numberType.equals("MOBILE")?-1:1;
        }
        

        但是,如果您以后想添加更多数字类型,最好使用enum

        【讨论】:

          【解决方案7】:

          如果您将NumberType 设为enum,而不是String,则其compareTo() 方法将根据声明枚举实例的顺序返回结果,而不是按字母顺序:

          public enum NumberType {
             MOBILE, HOME, OFFICE;
          }
          

          MOBILE 现在小于HOME 并且HOME 小于OFFICE。现在您可以使用自定义比较器对您的集合进行排序:

          list.sort(comparing(PhoneNumber::getNumberType).thenComparing(PhoneNumber::getNumber));
          

          【讨论】:

            【解决方案8】:

            有两种方法可以做到这一点。

            使用Comparator

            在这种方法中,您使用自定义ComparatorArrayList 进行排序。

            这是Comparator 代码。注意它是如何首先尝试对numberType 进行排序,然后是number

            public class PhoneNumberComparator implements Comparator<PhoneNumber> {
                @Override
                public int compareTo (PhoneNumber lhs, PhoneNumber rhs) {
                    int result = lhs.numberType.compareTo(rhs.numberType);
                    if (result == 0) {
                        result = lhs.number.compareTo(rhs.number);
                    }
                    return result;
                }
            }
            

            然后你可以调用:

            Comparator c = new PhoneNumberComparator();
            arrayListToSort.sort (c)
            

            现在,这本身不会完全起作用,因为numberType 的排序只是按字符串顺序排列的。最方便的排序方式是将numberType 设置为enumeration。这是代码:

            public enum NumberType { MOBILE, HOME, OFFICE }
            

            那么PhoneNumber必须被定义为numberTypeNumberType

            public class PhoneNumber {
                public String number ;
                public NumberType numberType;
            
                // .......
            
            }
            

            (顺便说一句,我鼓励你也将numbernumberType 变成private 变量,并按照JavaBeans standard 添加getter 方法。)

            制作PhoneNumber 实现Comparable

            如果您打算经常进行这种排序,那么您应该让PhoneNumber 实现Comparable 接口,而不是编写Comparator

            public class PhoneNumber implements Comparable <PhoneNumber> {
                public String number ;
                public NumberType numberType;
            
                // .......
            
                @Override
                public int compareTo (PhoneNumber rhs) {
                    int result = this.numberType.compareTo(rhs.numberType);
                    if (result == 0) {
                        result = this.number.compareTo(rhs.number);
                    }
                    return result;
                }
            }
            

            然后你可以打电话:

            arrayList.sort()
            

            您仍然需要将NumberType 设为enum,如第一种方法中所述。上面的compareTo() 实现依赖于NumberTypeComparable;所有enum 实例都自动成为Comparable

            注意ComparatorcompareTo() 实现之间的相似之处和不同之处。 ComparatorComparable can be found here 的一个很好的讨论。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-11-01
              • 1970-01-01
              • 2017-05-22
              • 1970-01-01
              • 2021-10-01
              相关资源
              最近更新 更多