排序Java通用对象的数组列表

时间:2019-01-15 17:46:46

标签: java sorting generics arraylist

我有一个Vertex类,它具有通用类型T的字段元素。

我有一个Vertex对象的ArrayList,我想对其进行排序,但是我不确定如何。

我尝试使用比较器,如下所示:

listOfNeighbours.sort(new Comparator<Vertex<T>>() {
        @Override
        public int compare(Vertex<T> v1, Vertex<T> v2) {
            if(v1.getElement() == v2.getElement()){
                return 0;
            }else if(v1.getElement() < v2.getElement()) {
                return -1;
            }else {
                return 1;
            }

         }
    });

显然,上述解决方案是错误的,因为我们无法比较泛型,但我希望与此类似的东西可以对我的Vertex对象列表进行排序。

在我的应用程序中,T可以是整数,双精度或字符串。

感谢您的帮助!

谢谢。

编辑:我的Vertex类在下面:

public class Vertex<T>{

private ObjectProperty<T> element;
private BooleanProperty visited;

public Vertex() {
    element = null;
    visited = new SimpleBooleanProperty(false);
}

public Vertex(T element) {
    this.element = new SimpleObjectProperty<T>(element);
    this.visited = new SimpleBooleanProperty(false);
}

public Vertex(T element, boolean visited) {
    this.element = new SimpleObjectProperty<T>(element);
    this.visited = new SimpleBooleanProperty(visited);
}

public void setElement(T elem) {
    this.element.set(elem);
}

public T getElement() {
    return this.element.get();
}

public ObjectProperty<T> elementProperty(){
    return this.element;
}

public void setVisited(boolean b) {
    this.visited.set(b);
}

public boolean isVisited() {
    return this.visited.get();
}

public BooleanProperty visitedProperty(){
    return this.visited;
}

@Override
public boolean equals(Object o) {
    if(o == this) {
        return true;
    }

    if(!(o instanceof Vertex<?>)) {
        return false;
    }

    Vertex<?> v=  (Vertex<?>) o;

    if(v.getElement() instanceof String) {
        return v.getElement().equals(this.element.get());
    }else {
        return v.getElement() == this.element.get();
    }


}

@Override
public String toString() {
    return element.get().toString();
}

}

3 个答案:

答案 0 :(得分:4)

Comparator是件好事。对于此特定问题,它具有static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)。就您而言,应该是

listOfNeighbours.sort(Comparator.comparing(Vertex::getElement))

如果您的Vertex组件不是Comparable,我建议您改用static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator),它可以与自定义比较器一起使用。

例如,

import java.util.*;
import javafx.beans.property.*;

public class Vertex<T>{

  private ObjectProperty<T> element;
  private BooleanProperty visited;

  public Vertex() {
      element = null;
      visited = new SimpleBooleanProperty(false);
  }

  public Vertex(T element) {
      this.element = new SimpleObjectProperty<T>(element);
      this.visited = new SimpleBooleanProperty(false);
  }

  public Vertex(T element, boolean visited) {
      this.element = new SimpleObjectProperty<T>(element);
      this.visited = new SimpleBooleanProperty(visited);
  }

  public void setElement(T elem) {
      this.element.set(elem);
  }

  public T getElement() {
      return this.element.get();
  }

  public ObjectProperty<T> elementProperty(){
      return this.element;
  }

  public void setVisited(boolean b) {
      this.visited.set(b);
  }

  public boolean isVisited() {
      return this.visited.get();
  }

  public BooleanProperty visitedProperty(){
      return this.visited;
  }

  @Override
  public boolean equals(Object o) {
      if(o == this) {
          return true;
      }

      if(!(o instanceof Vertex<?>)) {
          return false;
      }

      Vertex<?> v=  (Vertex<?>) o;

      if(v.getElement() instanceof String) {
          return v.getElement().equals(this.element.get());
      }else {
          return v.getElement() == this.element.get();
      }


  }

  @Override
  public String toString() {
      return element.get().toString();
  }

  public static void main(String[] args) {
    ArrayList<Vertex<String>> listOfNeighbours = new ArrayList<>();
    listOfNeighbours.add(new Vertex<>("foo"));
    listOfNeighbours.add(new Vertex<>("bar"));
    System.out.println(listOfNeighbours);
    listOfNeighbours.sort(Comparator.comparing(Vertex::getElement));
    System.out.println(listOfNeighbours);

    ArrayList<Vertex<Integer>> list2 = new ArrayList<>();
    list2.add(new Vertex<>(1));
    list2.add(new Vertex<>(123));
    list2.add(new Vertex<>(15));
    list2.add(new Vertex<>(2));
    System.out.println(list2);
    list2.sort(Comparator.comparing(Vertex::getElement));
    System.out.println(list2);
    list2.sort(Comparator.comparing(Vertex::getElement, Comparator.comparing(i -> i.toString())));
    System.out.println(list2);
  }
}

将如何完成(用https://www.compilejava.net/测试)。

结果是

[foo, bar]

(原始输入)

[bar, foo]

(按字符串排序)

[1, 123, 15, 2]

(原始输入)

[1, 2, 15, 123]

(按整数自然顺序排序)

[1, 123, 15, 2]

(按给定的字符串顺序,即从字法上来说)。

后者是通过Comparator<Vertex<Integer>>完成的,它通过提取给定Vertex<Integer>的值并将其转换为String(然后用作排序键)来完成其工作。

答案 1 :(得分:1)

如果将T限制为Comparable<? super T>,则上述@glglgl解决方案就足够了,因为似乎T可能基于该问题采用的任何类型都符合要求。

但是,如果T不受此限制,并且您不能或不想更改它,则解决方案会更通用一些,并且要求调用代码为{{ 1}}元素作为T

的第二个参数
Comparator.comparing

您无需为此定义单独的(静态)方法,如果愿意,可以内联。

对于元素类型类似于static <T> void sortNeightbours(Collection<Vertex<? extends T>> neighbours, Comparator<? super T> elementComparator) { neighbours.sort(Comparator.comparing(Vertex::getElement, elementComparator); } IntegerDouble的顶点,调用代码将相同:

String

您可以定义其他方法来处理Comparables,这样就不必每次都在代码中添加 List<Vertex<Integer>> ints = ...; List<Vertex<Double>> dbls = ...; List<Vertex<String>> strs = ...; sortNeighbours(ints, Comparator.naturalOrder()); sortNeighbours(dbls, Comparator.naturalOrder()); sortNeighbours(strs, Comparator.naturalOrder()); 调用。

答案 2 :(得分:0)

问题是,您想进行比较时是否知道顶点中的元素类型。

即由于类型擦除,此代码有效:

Vertex<String> strVtx = ...
Vertex<Integer> intVtx = ...
List<Vertex> list = Arrays.asList(strVtx, intVtx);
list.sort(aComparer);

因此,这里的比较器实现很困难。

但是,如果您知道类型,就可以轻松做到:

List<Vertex<Integer>> list = ...
list.sort(Comparator.comparing(Vertex::getElement);