Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 列表排序难题_Java_List_Sorting_Guava - Fatal编程技术网

Java 列表排序难题

Java 列表排序难题,java,list,sorting,guava,Java,List,Sorting,Guava,假设我有 final Iterable<String> unsorted = asList("FOO", "BAR", "PREFA", "ZOO", "PREFZ", "PREFOO"); (以必须首先出现的已知值开头的列表(此处为“PREFA”和“PREFZ”),其余按字母顺序排序) 我认为guava中有一些有用的类可以完成任务(排序、谓词…),但我还没有找到解决方案…注意:这不是最有效的解决方案。这只是一个简单、直接的解决方案,可以完成工作 我首先使用Collections.

假设我有

final Iterable<String> unsorted = asList("FOO", "BAR", "PREFA", "ZOO", "PREFZ", "PREFOO");
(以必须首先出现的已知值开头的列表(此处为“PREFA”和“PREFZ”),其余按字母顺序排序)


我认为guava中有一些有用的类可以完成任务(排序、谓词…),但我还没有找到解决方案…

注意:这不是最有效的解决方案。这只是一个简单、直接的解决方案,可以完成工作

我首先使用
Collections.sort(list)
对列表进行排序

然后,我会删除已知的项目,并将它们添加到前面

String special = "PREFA";
if (list.remove(special)
    list.add(0, special);
或者,如果前面有这些值的数组列表,则可以执行以下操作:

String[] knownValues = {};
for (String s: knownValues) {
    if (list.remove(s))
        list.add(0, s);
}

我也会使用
Collections.sort(list)
,但我认为我会使用一个比较器,在比较器中,您可以定义自己的规则,例如

class MyComparator implements Comparator<String> {

    public int compare(String o1, String o2) {
        // Now you can define the behaviour for your sorting.
        // For example your special cases should always come first, 
        // but if it is not a special case then just use the normal string comparison.

        if (o1.equals(SPECIAL_CASE)) {
            // Do something special
        }
        // etc.
        return o1.compareTo(o2);
    }

}

我会单独列出清单

一个用于已知值和未知值。并分别对它们进行排序,当您需要将它们放在一个列表中时,您可以将它们串联起来

knownUnsorted.addAll(unsorted.size - 1, unknonwUnsorted);
我建议填写你的价值观并使用

差不多

Collections.sort(myList, new FunkyComparator());
使用此选项:

class FunkyComparator implements Comparator {

    private static Map<String,Integer> orderedExceptions =
        new HashMap<String,Integer>(){{ 
            put("PREFZ", Integer.valueOf(1));
            put("PREFA", Integer.valueOf(2));
        }};

    public int compare(Object o1, Object o2) {
        String s1 = (String) o1;
        String s2 = (String) o2;
        Integer i1 = orderedExceptions.get(s1);
        Integer i2 = orderedExceptions.get(s2);

        if (i1 != null && i2 != null) {
            return i1 - i2;
        }
        if (i1 != null) {
            return -1;
        }
        if (i2 != null) {
            return +1;
        }
        return s1.compareTo(s2);
    }
}
类FunkyComparator实现Comparator{
私有静态映射orderedExceptions=
新的HashMap(){
put(“PREFZ”,Integer.valueOf(1));
put(“PREFA”,Integer.valueOf(2));
}};
公共整数比较(对象o1、对象o2){
字符串s1=(字符串)o1;
字符串s2=(字符串)o2;
整数i1=orderedExceptions.get(s1);
整数i2=orderedExceptions.get(s2);
如果(i1!=null&&i2!=null){
返回i1-i2;
}
如果(i1!=null){
返回-1;
}
如果(i2!=null){
返回+1;
}
返回s1.compareTo(s2);
}
}

因为我是番石榴酱的粉丝,所以我想用它找到一个解决方案。我不知道它是否有效,也不知道你是否觉得它和其他解决方案一样简单,但它在这里:

final Iterable<String> all = asList("FOO", "BAR", "PREFA", "ZOO", "PREFOO", "PREFZ");
final List<String> mustAppearFirst = asList("PREFZ", "PREFA");
final Iterable<String> sorted = 
      concat(
            Ordering.explicit(mustAppearFirst).sortedCopy(filter(all, in(mustAppearFirst))),
            Ordering.<String>natural().sortedCopy(filter(all, not(in(mustAppearFirst)))));
final Iterable all=asList(“FOO”、“BAR”、“PREFA”、“ZOO”、“PREFOO”、“PREFZ”);
最终列表必须首先显示为列表(“PREFZ”、“PREFA”);
最终Iterable排序=
海螺(
Ordering.explicit(mustAppearFirst).sortedCopy(filter(all,in)(mustAppearFirst)),
Ordering.natural().sortedCopy(过滤器(全部,而不是(在(mustAppearFirst '))));

你特别提到番石榴;除了Sylvain M的回答之外,还有另一种方法(更像是一种学术练习和番石榴灵活性的展示,而不是其他任何东西)

//这里的列表效率不高;对于大型问题,可以使用SkipList之类的工具
//这更合适
私有静态最终列表已知_索引=asList(“PREFZ”、“PREFA”);
私有静态最终函数在已知索引中的位置
=新函数(){
公共整数应用(中的对象){
int index=已知的索引。indexOf(in);
返回索引==-1?空:索引;
}     
};
...
列表值=asList(“FOO”、“BAR”、“PREFA”、“ZOO”、“PREFZ”、“PREFOO”);
集合。排序(值,
Ordering.natural().nullsLast().onResultOf(在已知索引中的位置)。component(Ordering.natural())
);
所以,换句话说,按
List.indexOf()
返回的
整数的自然顺序排序,然后断开对象本身的自然顺序


也许有些凌乱,但很有趣

list.remove()返回一个布尔值,而不是您删除的对象。但是我认为它可以工作:对于(最后一个字符串s:asList(“PREFA”,“PREFZ”){if(list.remove(s)){list.add(0,s);}}@Syl-Oops,我把这两个删除搞混了。我会解决它的,谢谢。不过你不能对一个Iterable进行排序,而首先将它转储到一个列表中会让它变得丑陋,因为在转储时你已经可以分离出未知项了。@unbeli:我同意你的看法,但现在,这似乎是最简单的方法job@Sylvain如果你想要最简单的方法,不要把它贴上“拼图”和“锻炼”的标签不错,但Set将消除重复项。另外,不需要dummy equals()嗯,如果我有两个以上的已知值,我如何转换它?@unbeli这两个观点都很好。由于从SortedSet切换到List不会改变我回答的要点,因此我已更新了列表的比较器的“用法”。@Sylvain\M,只需在
orderedExceptions
映射中添加所需数量的“已知值”。确保使用的整数是唯一的,并且按照您想要的顺序排列-映射保持查找速度,但是整数决定最终的顺序。哦,是的,所以维护起来并不太困难。谢谢,我觉得没问题,但我必须在条目中分开列表。方法不错。在我的回答中,我又尝试了一种“guavaey”方法,如果您对Hi Cowan感兴趣,我会尝试您的解决方案,但它不会编译。当我将其修改为编译时(通过在排序和帮助类型推断上添加asList()),我得到了一个NPE…对不起,Sylvain,我写这篇文章时没有接近编译器。我已经修好了。出于某种原因,我认为
Ordering.component()
是一种静态方法;您还需要
nullsLast().onResultOf()
而不是
onResultOf().nullsLast()
,否则它会以错误的顺序链接内容。现在对我来说是可行的。因为有人建议我接受一个答案,我接受这个答案,因为这是我读过的最简洁的答案。嗯,这是主观的,但这是我的首选答案(简洁+使用番石榴)我必须接受这种练习的解决方案吗?
class FunkyComparator implements Comparator {

    private static Map<String,Integer> orderedExceptions =
        new HashMap<String,Integer>(){{ 
            put("PREFZ", Integer.valueOf(1));
            put("PREFA", Integer.valueOf(2));
        }};

    public int compare(Object o1, Object o2) {
        String s1 = (String) o1;
        String s2 = (String) o2;
        Integer i1 = orderedExceptions.get(s1);
        Integer i2 = orderedExceptions.get(s2);

        if (i1 != null && i2 != null) {
            return i1 - i2;
        }
        if (i1 != null) {
            return -1;
        }
        if (i2 != null) {
            return +1;
        }
        return s1.compareTo(s2);
    }
}
final Iterable<String> all = asList("FOO", "BAR", "PREFA", "ZOO", "PREFOO", "PREFZ");
final List<String> mustAppearFirst = asList("PREFZ", "PREFA");
final Iterable<String> sorted = 
      concat(
            Ordering.explicit(mustAppearFirst).sortedCopy(filter(all, in(mustAppearFirst))),
            Ordering.<String>natural().sortedCopy(filter(all, not(in(mustAppearFirst)))));
// List is not efficient here; for large problems, something like SkipList 
// is more suitable
private static final List<String> KNOWN_INDEXES = asList("PREFZ", "PREFA");

private static final Function<Object, Integer> POSITION_IN_KNOWN_INDEXES 
    = new Function<Object, Integer>() {
  public Integer apply(Object in) {
     int index = KNOWN_INDEXES.indexOf(in);
     return index == -1 ? null : index;
  }     
};


...


List<String> values = asList("FOO", "BAR", "PREFA", "ZOO", "PREFZ", "PREFOO");

Collections.sort(values,
  Ordering.natural().nullsLast().onResultOf(POSITION_IN_KNOWN_INDEXES).compound(Ordering.natural())
);