将 List<Object[]> 转换为 List<Integer> 时出现歧义

Ambiguities while converting List<Object[]> to List<Integer>

我们尝试使用 hibernate 通过 SQL 查询从数据库中获取结果,如果存在记录,这将 return List<Object[]>。但是后面我们想把它转换成一个List<Integer>。因此,我们没有遍历 Object[] 列表并继续添加到整数列表,而是尝试了一些方法,示例代码类似于

public class ListObjectArrayToListInteger {
    public static void main(String[] args) {
        Object[] ob1 = {1};
        Object[] ob2 = {5};
        Object[] ob3 = {9};
        List objList = new ArrayList();
        objList.add(ob1);
        objList.add(ob2);
        objList.add(ob3);

        //Case - 1
        List<Integer> intList = objList;
        System.out.println(intList);

        //Case - 2          
        List<Integer> intList = new ArrayList<Integer>();
        intList.addAll(objList);
        System.out.println(intList);
    }
}

我们只是试图从查询中获取一列,这就是为什么所有 Arrays 都只有一个元素的原因。 Case-1Case-2 都是分别执行的,两种情况下的输出都是一样的,就像这样

[[Ljava.lang.Object;@3e25a5, [Ljava.lang.Object;@19821f, [Ljava.lang.Object;@addbf1]

Case-1 intList 中,List<Integer> 的类型指向 List 的对象 Object[]秒。我们期望在 运行 时间内出现异常,因为数据类型完全不同。

Case-2 中,我们明确地将 Object[]s 添加到 List<Integer> 并且毫无例外地给出了据我所知的输出奇怪。

  1. 那么谁能解释为什么我们会得到这样的输出?
  2. 一个 List<Integer>,在它的所有位置只期望 Integers,如何保存这样的数据 [[Ljava.lang.Object;@3e25a5, [Ljava.lang.Object;@19821f]
  3. 为什么 Java 允许用户将数据从原始数据列表添加到通用列表。在我的代码中,如果我使 Object[] ob1 = {1, 2, "3", "abc"}; 它可以添加到 intList 作为 intList.addAll(objList); 这是允许的并且 运行s 顺利。

在休眠状态下,数组中的每个对象都代表一个选定的实体 (table)。

最好将查询限制为所需的结果:

  String hql = "select count(me.grp) from  MyEntity me group by grp";
  TypedQuery<Integer> query = entityManager.createQuery(hql, Integer.class);
  List<Integer> result = query.getResult();

假设您也需要扩展数据用于其他目的:

  List<Integer> result = objList.stream()
          .map(oarr -> oarr[0])
          .map(Integer.class::cast)
          .collect(Collectors.toList());

对于休眠查询 select A a, B b, C c 不是 int,而是 class A:

List<Object[]> objList = ...

List<Integer> result = objList.stream()
          .map(oarr -> oarr[0])           // Object[] to Object
          .map(A.class::cast)             // Object to A
          .map(A::getId)                  // A to int A.getId()
          .collect(Collectors.toList());

上代码

如果键入 objList,它将不会编译。

    List<Object[]> objList = new ArrayList<>();

如果没有类型参数,整个泛型类型就不会适用于 objList,因此甚至适用于 intList。使用类型擦除 intList 只是一个对象列表,并且一切正常。

@A运行 Sudhakaran,你问的三个问题可以这样回答:

问题一:

案例一:

你说:intList List<Integer> 的类型指向 ListObject[] 对象s ".

这是不正确的,因为您没有使用参数 <Object[]> 初始化 objList;您正在像这样初始化 objListList objList = new ArrayList();.

这样,objList 将创建为 Listraw-type,而不是 List输入 Object[].

(更多关于 raw-type: https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html

因为 intListList<Integer> 的类型,这意味着 intList 指向 List 的对象 raw-type- 不是类型为 Object[]s.List 的对象。

JDK 1.5 以来,泛型一直是 Java 的一部分。为了保持向后兼容性,Java 没有删除使用 raw-type.

的集合初始化
//Case - 1
List<Integer> intList = objList;

在这种情况下,objList 被初始化为 raw-type。通过将 intList 指向 objList,编译器不知道 objList 集合变量持有的值的类型。这就是编译器允许您将 Object 的数组添加到 objList.

的原因

案例二:

//Case - 2          
List<Integer> intList = new ArrayList<Integer>();
intList.addAll(objList);
System.out.println(intList);

你说:" 我们明确地向 List<Integer> 添加了 Object[]s 并且毫无例外地给出了输出 "

同样,这是不正确的。您正在将 Object[] 类型的 List 添加到 List<Integer> 中,而不是将 Object[] 类型添加到 List<Integer> 中。你不是在做 intList.add(ob1); intList.add(ob2);。如果你这样做,那么你可以说我们正在将 Object[]s 添加到 List<Integer>.

JDK 1.5 开始,您可以使用泛型来初始化集合变量,如下所示:

List<Integer> list = new ArrayList<>(); //or
List<?> list = new ArrayList<>();

之后,当尝试将元素添加到 list 时,编译器将检查元素是否具有与 list 相同的数据类型或与 [=46] 相同的 sub-type =].当您将鼠标悬停在 IDE(如 eclipse 或 intelliJ)中的集合变量上时,您可能会看到类似 List<? extends Integer>.

的内容

但是这里,objList 是用 raw-type 初始化的,不是泛型。这意味着编译器不知道 objList 不是 Integer 或 sub-type Integer 类型。如果是这种情况,编译器将不会抛出异常。相反,编译器会遍历列表并给出ob1ob2和`ob3.

的引用值

问题二:

当试图将 objList 的所有元素添加到 List<Integer> 时,在编译时,编译器将不知道 objList 的 data-type 因为 objList属于raw-type。因此,编译器不会抛出异常。相反,编译器将允许用户将此类元素添加到 List<Integer> 中。当尝试遍历 List<Integer> 时,您会发现 objList 中元素的参考值是 ob1ob2ob3.

问题三:

Java 只允许用户将原始数据列表中的数据添加到通用列表中。这样做是为了支持 兼容性 ,这也是您的代码在 JDK 1.4 和 运行 中顺利 运行 的原因=107=]JDK 1.8 无需更改任何代码。