如何为 Java 中的灵活类型数组制作类型特定的比较器
How to make a type specific Comparator for a flexible type array in Java
我被困在 'generic-type-qualifier-land' 中间,找不到类型限定符的正确组合。我有一个 class 代表一个灵活的数组,其中可以有许多不同的类型。 class 持有一个 ArrayList<Object>
作为元素的容器。
class MyArray {
ArrayList<Object> list;
...
public void sortAsString(Comparator<String> comp) {
Collections.sort(list, comp);
}
}
有类型特定的访问器,如 getString(i)
和 getInt(i)
等
我希望能够以不同的方式对这个数组进行排序。有时数组中充满了字符串,我希望人们能够传入一个 Comparator<String>
对象。如果我如上所述声明 class,编译器会拒绝它,因为列表是 Object
的集合,而比较器是 Comparator<String>
但我也不会打字。这不起作用:
public void sortAsString(Comparator<String> comp) {
Coparator<Object> foo = (Comparator<Object>) comp;
Collections.sort(list, foo);
}
Collections.sort函数第二个参数需要Comparator<? super Object>
。有什么方法可以声明方法 and/or 进行类型转换,以便有人可以传递 Comparator<String>
并让它在这个 ArrayList<Object>
上工作?
我也尝试将列表转换为 ArrayList<String>
,但这也是不允许的。在调用它的情况下,用户将相当确定数组中只有字符串,但当然我们在编译时不知道这一点。我试图告诉它,即使它没有被声明为字符串数组,也可以像对待排序一样对待它。我不在乎当成员对象不是字符串时它是否会爆炸。我只是一些语法糖告诉编译器继续并让它调用排序方法。
只需使用原始类型。这编译
public void sortAsString(Comparator<String> comp) {
List<Object> list = null;
Comparator foo = comp;
Collections.sort(list, foo);
}
假设您绝对确定 ArrayList<Object>
仅包含 String
,并且您已做好崩溃的准备,如果那不是案例...
您可以从 Comparator<String>
创建一个 Comparator<Object>
,如果将非 String
传递给它,它将崩溃:
Collections.sort(list, (x, y) -> comp.compare((String)x, (String)y));
我建议在此之前检查是否所有对象都是字符串,如果不是这样,则抛出一个有意义的异常message/do什么都没有。
您正试图将列表转换为 ArrayList<String>
(或者可能只是 List<String>
)。不过,编译器将此标记为错误,因为通常它绝对不安全。
如果调用者进行此调用是安全的,您可以使用“cast through raw”技术来避免编译错误。您仍然会收到未经检查的警告,然后您可以将其抑制。此外,在进行不安全转换之前检查列表的内容可能是个好主意。这允许您验证您正在做的事情实际上是安全的,或者如果不是,您可以以适当的方式将其传达给调用者——可能通过抛出异常。例如,
public void sortAsString(Comparator<String> comp) {
if (! list.stream().allMatch(o -> o instanceof String)) {
throw new IllegalStateException("MyArray contains non-strings");
}
@SuppressWarnings("unchecked")
ArrayList<String> temp = (ArrayList<String>)(ArrayList)list;
temp.sort(comp);
}
我被困在 'generic-type-qualifier-land' 中间,找不到类型限定符的正确组合。我有一个 class 代表一个灵活的数组,其中可以有许多不同的类型。 class 持有一个 ArrayList<Object>
作为元素的容器。
class MyArray {
ArrayList<Object> list;
...
public void sortAsString(Comparator<String> comp) {
Collections.sort(list, comp);
}
}
有类型特定的访问器,如 getString(i)
和 getInt(i)
等
我希望能够以不同的方式对这个数组进行排序。有时数组中充满了字符串,我希望人们能够传入一个 Comparator<String>
对象。如果我如上所述声明 class,编译器会拒绝它,因为列表是 Object
的集合,而比较器是 Comparator<String>
但我也不会打字。这不起作用:
public void sortAsString(Comparator<String> comp) {
Coparator<Object> foo = (Comparator<Object>) comp;
Collections.sort(list, foo);
}
Collections.sort函数第二个参数需要Comparator<? super Object>
。有什么方法可以声明方法 and/or 进行类型转换,以便有人可以传递 Comparator<String>
并让它在这个 ArrayList<Object>
上工作?
我也尝试将列表转换为 ArrayList<String>
,但这也是不允许的。在调用它的情况下,用户将相当确定数组中只有字符串,但当然我们在编译时不知道这一点。我试图告诉它,即使它没有被声明为字符串数组,也可以像对待排序一样对待它。我不在乎当成员对象不是字符串时它是否会爆炸。我只是一些语法糖告诉编译器继续并让它调用排序方法。
只需使用原始类型。这编译
public void sortAsString(Comparator<String> comp) {
List<Object> list = null;
Comparator foo = comp;
Collections.sort(list, foo);
}
假设您绝对确定 ArrayList<Object>
仅包含 String
,并且您已做好崩溃的准备,如果那不是案例...
您可以从 Comparator<String>
创建一个 Comparator<Object>
,如果将非 String
传递给它,它将崩溃:
Collections.sort(list, (x, y) -> comp.compare((String)x, (String)y));
我建议在此之前检查是否所有对象都是字符串,如果不是这样,则抛出一个有意义的异常message/do什么都没有。
您正试图将列表转换为 ArrayList<String>
(或者可能只是 List<String>
)。不过,编译器将此标记为错误,因为通常它绝对不安全。
如果调用者进行此调用是安全的,您可以使用“cast through raw”技术来避免编译错误。您仍然会收到未经检查的警告,然后您可以将其抑制。此外,在进行不安全转换之前检查列表的内容可能是个好主意。这允许您验证您正在做的事情实际上是安全的,或者如果不是,您可以以适当的方式将其传达给调用者——可能通过抛出异常。例如,
public void sortAsString(Comparator<String> comp) {
if (! list.stream().allMatch(o -> o instanceof String)) {
throw new IllegalStateException("MyArray contains non-strings");
}
@SuppressWarnings("unchecked")
ArrayList<String> temp = (ArrayList<String>)(ArrayList)list;
temp.sort(comp);
}