此类是出现问题的示例:
public class ContainsSet {
private static HashSet<E> myHashSet;
[...]
public static Set<E> getMyHashSet() {
return new HashSet<E>(myHashSet);
}
public static boolean doesMyHashSetContain(E e) {
return myHashSet.contains(e);
}
}
现在想象两个可能的功能:
boolean method1() {
return ContainsSet.getMyHashSet().contains(someE);
}
boolean method2() {
return ContainsSet.doesMyHashSetContain(someE);
}
现在我的问题是,方法1在Java优化之后是否具有与方法2相同的时间复杂度。
(我使用HashSet
而非Set
来强调myHashSet.contains(someE)
具有复杂性O(1)
。)
没有优化就不会。虽然.contains()
具有复杂性O(1)
,但new HashSet<E>(myHashSet)
具有复杂性O(n)
,这会使方法1的复杂度为O(n) + O(1) = O(n)
,这与心爱的{{}}相比非常糟糕O(1)
{1}}。
我导入此问题的原因是因为如果您不允许外部类更改其内容,我会被教导不返回列表或集合。返回副本是一个显而易见的解决方案,但它可能非常耗时。
答案 0 :(得分:7)
不,javac
没有(也不能)优化这一点。需要将源中描述的字节代码发送到此级别。并且JVM几乎不够智能,无法优化它。它太可能有副作用来证明。
如果您想要不变,请不要返回HashSet
的副本。将其包装在不可修改的包装器中:Collections.unmodifiableSet(myHashSet)
答案 1 :(得分:0)
我可以在这里说什么,但是创建一个新的HashSet并通过构造函数填充它是很昂贵的!
Java不会&#34;优化掉&#34;这项工作:即使你和我知道它会产生与#34相同的结果;通过&#34; contains()调用,java无法知道这一点。
答案 2 :(得分:0)
没有。这超出了优化范围。你返回了一个新对象,你可以在其他地方使用它,Java不应该省略它。将创建一个新的HashSet。
返回副本不是一个好习惯。这不仅耗费时间,而且耗费空间。正如Sean所说,你可以用unmodifiableSet包装,或者你可以将它包装在你自己的类中。
你可以试试这个:
public static Set<E> getMyHashSet() {
return Collection.unmodifiableSortedSet(myHashSet);
}
注意:使用该方法将返回您的集合的视图,而不是副本。