用户定义使用Java 8中的Stream进行排序

时间:2017-03-29 15:35:52

标签: java java-8 java-stream

我是Java 8 Stream API的新手。我有以下要求我的订购规则是:“A”,“C”,“D”,“B”
   我的结果是包含8-9个元素和重复元素的对象。

以下是我的代码:

public class A
{
private String name;
    public A()
    {
    }
    public A(String name )
    {
     this.name=name;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "A [name=" + name + "]";
    }

我有另一个班级:

public class B
{
   enum TypeEnum{
    A("A"),
    C("C"),
    D("D"),
   B("B");

    private String s;

    private TypeEnum(String s) {
        this.s = s;
    }
}

public static void main(String agrs[] )
   {

   Collection<A> stringCollection = new ArrayList<>();
    stringCollection.add(new A("A"));
    stringCollection.add(new A("D"));
    stringCollection.add(new A("D"));
    stringCollection.add(new A("C"));
    stringCollection.add(new A("D"));
    stringCollection.add(new A("B"));
    stringCollection.add(new A("A"));
    stringCollection.add(new A("A"));

    Predicate<A> aPredicate = a -> a.getName() == TypeEnum.A.name();
    Predicate<A> cPredicate =  a -> a.getName()== TypeEnum.C.name();
    Predicate<A> dPredicate =  a -> a.getName()== TypeEnum.D.name();
    Predicate<A> bPredicate =  a -> a.getName()== TypeEnum.B.name();

    Predicate<A> fullPredicate = aPredicate.and(cPredicate)
            .and(dPredicate).and(bPredicate);

    List<A> list= stringCollection.stream().filter(fullPredicate).collect(Collectors.toList());

    System.out.println(list);
    }

此处输出应为A,A,A,C,D,D,D,B

我想按照上面提到的使用Stream java 8 API按照指定的规则对元素进行排序。 A类是一个在B类中使用的对象,用于将值放入列表中,该类型是A类。最终结果应按照定义的排序规则排序。如果任何人面对同样的问题并为此提供解决方案,那将是非常好的和感恩的。

1 个答案:

答案 0 :(得分:2)

您可以按给定列表的位置进行排序:

List<String> order = Arrays.asList("A", "C", "D", "B");
List<A> result = collection.stream()
    .sorted(Comparator.comparingInt(a -> order.indexOf(a.getName())))
    .collect(Collectors.toList());

这会将未在列表中指定的名称放在前面。您可以使用比较器Comparator.comparingInt(a -> order.indexOf(a.getName())+Integer.MIN_VALUE)将它们移到最后。

由于重复使用indexOf,对于较大的order列表,这不会很好地扩展。

另一种选择是存储桶排序变体:

Map<String, List<A>> m = collection.stream().collect(Collectors.groupingBy(A::getName));
List<A> result = Stream.of("A", "C", "D", "B")
    .flatMap(s -> m.getOrDefault(s, Collections.emptyList()).stream())
    .collect(Collectors.toList());

此处,未指定的名称根本不会显示在结果中。它会有更好的时间复杂度,但可能暂时消耗更多内存。

相关问题