【问题标题】:Sort a list with element still in first position对元素仍位于首位的列表进行排序
【发布时间】:2010-05-18 12:06:07
【问题描述】:

我有一个字符串列表:

List<String> listString  = new ArrayList<String>();
listString.add("faq");
listString.add("general");
listString.add("contact");

我对列表进行了一些处理,我想对这个列表进行排序,但我希望“general”始终排在第一位。 谢谢 ;)

【问题讨论】:

  • "general" 不在第一位。请澄清。
  • @Marcelo 现在 OP 已经接受了答案,这意味着代码是正确的,问题是错误的,所以我已经编辑了。

标签: java list sorting


【解决方案1】:

我喜欢@Petar 的方法,但另一种方法是使用自定义比较器对其进行排序,该比较器总是说“一般”在被比较的任何东西之前。

Collections.sort(list, new Comparator<String>()
  {
     int compare(String o1, String o2)
     {
         if (o1.equals(o2)) // update to make it stable
           return 0;
         if (o1.equals("general"))
           return -1;
         if (o2.equals("general"))
           return 1;
         return o1.compareTo(o2);
     }
});

【讨论】:

  • 是的,我只是发布了一个示例,但是如何使用总是说“一般”在任何东西之前的比较器?
  • 在 compare 方法中首先执行特定的if-statement,检查其中一个输入是否等于“general”。
  • 实际上,这可能不稳定,具体取决于 Collections.sort 使用的算法,因此您可能需要先测试 o1 和 o2 是否相等,然后再将它们与“general”进行比较。
  • 这种方法可以得到“java.lang.IllegalArgumentException:Compare method违反了它的一般约定!”。
  • @PavelKataykin 正如我在您之前的评论中提到的那样,它可能会导致问题,因为它不稳定,但我认为如果您先添加 if (o1.equals(o2)) return 0; 就可以了。
【解决方案2】:

改为在其subList 上执行Collections.sort。

    List<String> list = new ArrayList<String>(
        Arrays.asList("Zzz...", "Two", "One", "Three")
    );
    Collections.sort(list.subList(1, list.size()));
    System.out.println(list);
    // "[Zzz..., One, Three, Two]"

API 链接

  • subList(int fromIndex, int toIndex)
    • 返回此列表在指定fromIndex(包括)和toIndex(不包括)之间的视图。返回的列表由该列表支持,因此返回列表中的非结构性更改会反映在该列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。

如果特殊元素不在索引 0 处,则只需将其放在那里,然后按如下方式对其进行排序:

    List<String> list = new ArrayList<String>(
        Arrays.asList("Four", "Five", "Zzz...", "Two", "One", "Three")
    );
    Collections.swap(list, list.indexOf("Zzz..."), 0);
    Collections.sort(list.subList(1, list.size()));
    System.out.println(list);
    // "[Zzz..., Five, Four, One, Three, Two]"

API 链接

【讨论】:

  • 是的,但在他的示例中,“Zzz...”排在第二位:)
  • 我的意思是谁说它会像您的示例代码一样始终位于首位。
  • @Petar:这就是问题需要澄清的原因。我的答案是如何对列表中的元素进行排序,除了第一个。也就是List的subList(1,...)如何排序。
  • 我实际上认为这比 Petar 的答案可读性差。在他的回答中,很明显第一项是一种特殊情况,并且非常明确的是“General”应该放在首位。如果您不知道第一个元素是什么,这无疑会更好,但否则我会选择显式解决方案。
  • @Petar 测试它。它完美地工作,假设“一般”实际上是第一位的,正如 OP 的问题所述(但代码没有显示)
【解决方案3】:

对列表进行排序,其中不包含“general”,然后将其添加到开头。

【讨论】:

  • 可怕的黑客攻击。请改用subList,看看我的回答。
  • @poly,我强烈反对这是一个“可怕的黑客”。它非常简单且有效。
  • @Paul:这很糟糕,因为它进行了不必要的结构修改(删除然后添加)。
  • @poly,这在很大程度上取决于此列表是构建一次还是多次。如果它只构建一次,那么添加除“general”之外的所有内容是合理的,对其进行排序,然后将“general”添加到前面。它是多次构建的,或者是在构建后修改的,那么是的,这是一个糟糕的选择。
【解决方案4】:

您可以使用以下代码 sn-p,但对于非常大的列表,它可能会出现性能/内存问题。

public static List<String> sortSpecial(List<String> list, final String alwaysOnTopItem) {
    list.remove(alwaysOnTopItem);
    Collections.sort(list);

    List<String> result = new ArrayList<String>(list.size() + 1);
    result.add(alwaysOnTopItem);
    result.addAll(list);

    return result;
}

public static void main(String[] args) {
    List<String> listString = new ArrayList<String>();
    listString.add("faq");
    listString.add("general");
    listString.add("contact");
    String alwaysOnTopItem = "general";
    List<String> sortedList = sortSpecial(listString, alwaysOnTopItem);
    System.out.println(sortedList);
}

【讨论】:

    【解决方案5】:

    不错!问题。如果我们想固定第一个和最后一个元素的位置,那么我们可以增强@Paul Tomblin's 方法,如下所示。请复制代码并尝试一下。

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    public class CustomComparatorToFixedPosition {
    
      public static void main(String[] args) {
        List<Emp> empNames = new ArrayList<>();
        empNames.add(new Emp("name1"));
        empNames.add(new Emp("LastName"));
        empNames.add(new Emp("name2"));
        empNames.add(new Emp("FirstName"));
        empNames.add(new Emp("name3"));
        getSortedName(empNames).stream().forEach(emp -> System.out.println(emp.getName()));
      }
    
      public static List<Emp> getSortedName(List<Emp> empNames) {
        String first = "FirstName";
        String last = "LastName";
        Collections.sort(empNames, new Comparator<Emp>() {
          public int compare(Emp o1, Emp o2) {
            if (o1.getName().equalsIgnoreCase(first) || o2.getName().equalsIgnoreCase(last))
              return -1;
            if (o2.getName().equalsIgnoreCase(first) || o1.getName().equalsIgnoreCase(last))
              return 1;
            return o1.getName().compareTo(o2.getName());
          }
        });
        return empNames;
      }
    }
    
    class Emp {
    
      private String name;
    
      Emp(String name) {
        this.name = name;
      }
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-27
      • 1970-01-01
      • 2018-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多