【问题标题】:Java safe return type containerJava 安全返回类型容器
【发布时间】:2016-10-18 02:08:54
【问题描述】:

我白天是一名 c++ 开发人员,并且习惯于 const 返回类型的约定。我知道java中没有类似的工具。

我有一个特定的情况,想知道最适合我的任务的不可变集合。在 C++ 中,我只会使用 std::vector。

我有一个 WavFile 类,它当前有一个 float[] 数据,我想用不可变的东西替换它。

关于容器的一些重要规定是它的大小在创建时是已知的,它根本不需要动态增长或收缩。其次,索引到容器中应该是 O(1)。

最重要的是,正如主题所暗示的那样,我希望能够拥有一个返回此容器的不可变版本的 getter。

我要查找的容器类型是什么?这在java中是可能的吗?

【问题讨论】:

  • 您需要自己的容器包装 float[] 数组。任何基于 Java 泛型的集合在存储量方面都会有太多的开销,在引用的局部性方面甚至会产生更多的开销。编写满足您要求的自己的容器。 Getter 应该为调用者制作一个防御性的数组副本。
  • 我认为避免通过设计暴露内部数据的更好方法。如果您的目标只是让人们遍历每个浮点数,而不是公开内部数据,为什么不简单地公开DoubleStream getDataStream() 甚至void forEachDataPoint(DoubleConsumer consumer)?如果您希望人们进行某种随机访问,您还可以公开类似float dataPoint(int index); float[] dataPoints(int from, int to);

标签: java arrays collections


【解决方案1】:

如果您可以接受装箱费用,Collections.unmodifiableList()Guava ImmutableList 将起作用。

如果没有,请尝试Trove,它提供TFloatArrayListan easy way to make them unmodifiable

【讨论】:

  • “其次,索引到容器中应该是 O(1)...” - 你的任何建议都符合吗?
  • @MordechayS – java.util.ArrayList 是使用数组实现的。我们可以在 O(1) 时间内建立索引...arrayList.get( /*int index*/ );
  • @wfunston 谢谢!那么,不仅 Trove API 是一个有效的答案吗?
  • @MordechayS – Trove 不是唯一的答案。在这种情况下,Collections 是 java API 中的一个类。 java.util.Collections。 ArrayList 是 Collections 的子类(孙子)。
【解决方案2】:

恕我直言,最好通过设计解决问题。返回一个集合或数组,即使它是const,仍然是不令人满意的 OO 设计,因为您正在公开内部数据(尽管不如将其公开为公共成员变量那么糟糕)。

您可能会进一步考虑人们应该如何使用这些数据。

如果您希望人们简单地遍历每个数据点,那么您可以提供类似

public class WaveFile {
    public DoubleStream dataStream() {...}
    public forEachDataPoint(DoubleConsumer consumer) {...}
}

如果你真的想让人们做随机访问,你可以提供

public class WaveFile {
    public float dataPointAt(int index) {...}
    public DoubleStream dataStream(int fromIndex, int toIndex) {...}
}

这种封装避免了许多意想不到的数据使用方式,并为您在内部表示数据的方式提供了很大的灵活性。例如,您可以从磁盘上的文件进行延迟加载,您可以制作一个“WaveFile”,通过某些公式等动态生成数据点。

【讨论】:

  • 不同意。通过getter“暴露内部数据”返回一个int?返回一个 const 向量是很好的设计。会出什么问题?
  • 这实际上是一个问题,因为您仍然将对象视为提供数据的东西,而不是承载行为的东西。 “getter 总是错误的”并不是一条黄金法则,有些情况是必需的,例如,作为值对象(其真正旨在提供数据)。使用 getter/setter,虽然比 public 成员 var 好,但离正确封装还很远。
  • 我想这个著名的辩论是OOP开发者应该知道的,应该明白双方背后的原因:javaworld.com/article/2073723/core-java/…
  • 好吧,你可能会选择不继续学习正确的 OO 设计习语和原则,而是坚持“所谓的 OO-but-in-fact-procedural”的思维方式,但是我认为简单地称其为“妄想”是不恰当的。
猜你喜欢
  • 2013-01-02
  • 1970-01-01
  • 2011-08-26
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-15
相关资源
最近更新 更多