【问题标题】:How to sum arrays in Java如何在 Java 中对数组求和
【发布时间】:2013-06-28 10:13:14
【问题描述】:

我正在编写一个函数来对 Java 中的两个数组(不一定相等大小)求和并返回结果。

这是我的尝试:

 public static <T> T[] sumArrays(T[] lhs, T[] rhs)
    {
        T[] out = new T[Math.max(lhs.length, rhs.length)];

        for (int i = 0; i < Math.max(lhs.length, rhs.length); ++i){            
            if (i < Math.min(lhs.length, rhs.length)){
                out[i] = lhs[i] + rhs[i];                
            } else if (i < lhs.length){
                out[i] = lhs[i];
            } else /* if (i < rhs.length)*/{
                out[i] = rhs[i];
            }            
        }
        return out;        
    }

尽管有编译错误,但我有几个观察结果。

  1. 为什么Java库中没有这个功能,巨大无比?

  2. 我很想使用泛型,就像您在 C++ 中使用模板一样。

  3. 我担心获取输入数据的深层副本; lhs 和 ``rhs.任何人都可以让我放心吗? C++ 允许我传递一个常量引用;我肯定会知道的。

  4. T[] out 的实例化对于泛型类型似乎是非法的。我错过了什么?

  5. 编译器会优化掉我重复的Math.max(lhs.length, rhs.length)吗?

  6. 编译器不喜欢lhs[i] + rhs[i]。大概是因为它不知道 T 的类型,但是 C++ 允许您这样做,因为它在知道类型之前不会尝试编译模板。

  7. 返回时是否要取出深层副本?同样,C++ 编译器不会额外复制一份。

也许我太老了,无法习惯 Java;-)

【问题讨论】:

  • 添加两个长度不等的数组的内容实际上并不是一个常见的活动,我从来没有做过。如果是这样,那么如何划分两个数组,减去两个数组,将一个数组中的一个条目提升到另一个数组的幂等等等等。Java 为您提供了在需要时执行此操作的工具
  • T 在运行时是未知的,这就是为什么你不能做new T[]
  • And + 仅适用于原语(和字符串)而不是所有对象,因此鉴于您已将此函数声明为准备接受编译器不能允许的 anything你用 +

标签: java


【解决方案1】:

1)为什么在极其庞大的Java库中没有这个功能?

征求意见,这里跑题了。

3) 我担心得到输入数据的深层副本;左手和右手。任何人都可以让我放心吗? C++ 允许我传递一个常量引用;我肯定会知道的。

7) 返回时是否要取出深层副本?同样,C++ 编译器不会额外复制。

在 Java 中不会自动进行深度复制。此外,深度复制通常是一个定义不明确的问题。

4) T[] out 的实例化对于泛型类型似乎是非法的。我错过了什么?

除了不可能实例化泛型类型的数组之外,泛型类型仅涵盖引用类型。你很可能在这里只对原始类型感兴趣,所以它们没有用。

5) 编译器会优化掉我重复的Math.max(lhs.length, rhs.length)吗?

有些 JIT 可能会,但您不能有任何保证。提取到局部变量。

6) 编译器不喜欢lhs[i] + rhs[i]。大概是因为它不知道 T 的类型,但 C++ 允许您这样做,因为它在知道类型之前不会尝试编译模板。

很遗憾,您在这里遇到了很多麻烦。没有办法将算法泛化到所有原始 Java 类型。

【讨论】:

  • 嗯,但是 +1。不应将其解释为批评,因为 Java 在考虑如何改进其他语言时欠它的优雅,但以上所有内容都可以在 C++ 中使用模板轻松完成。我想我应该使用 double 代替 T 构建一个版本。
  • @Bathsheba 在 C++ 中,如果您尝试(例如)将一个篮球添加到另一个篮球中会发生什么?如您所写,您的代码允许这样做(如果编译器不反对)
  • C++ 模板在编译时使用特定类型实例化,因此它们与 Java 泛型几乎没有关系。是的,JG 是 Java 的一个相当软弱的特性,具有可怕的推重比,并且已经受到了很多批评。
  • @Richard Tingle;在 C++ 中,如果操作有意义,则可以重载运算符,如果不是,则允许(甚至强制)编译时错误。
  • @Bathsheba 然而,它的签名明确指出它会接受任何东西(就像数组列表会接受任何东西),它实际上不是编译时错误,而是运行时异常(讨厌)。如果你能说出任何原始的东西(并且对于对象,你可以使用 extends ParentClass 来做到这一点)但不能使用原始语言,那就太好了。 Primatives 只存在于 java 中,因为它们公认比它们的 Object 兄弟(Integer、Double 等与 int、double 等)更快。因此,原语在 java 中是非常二等公民
【解决方案2】:

6) 编译器不喜欢 lhs[i] + rhs[i]。大概是因为它 不知道 T 的类型,但 C++ 允许您这样做 在知道类型之前不要尝试编译模板。

你总是可以用 .add(...) 函数编写一个接口,然后让 T 扩展这个接口。然后你可以写 lhs[i].add(rhs[i])

【讨论】:

    猜你喜欢
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 2010-12-05
    • 1970-01-01
    相关资源
    最近更新 更多