创建一个类,用作 String 对象的不可变列表。
我决定利用 Google Guava 的 ImmutableList<E> 集合,而不是包装一个简单的 List<E> 使用 Collections.unmodifiableList(List<? extends T> list) 因为我理解这可以避免对后备 List<E> 进行不必要的并发检查,后者不知道被包装(来源:{{ 3}})。
这里有一些尝试,尽管可能有更多的组合。原谅幽默的演绎。
import java.util.List;
import com.google.common.collect.ImmutableList;
class BritnetSpearsSpellings implements Iterable<String> {
public static BritnetSpearsSpellings of(String... spellings) {
BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings();
britneySpears.spellings = ImmutableList.copyOf(spellings);
return britneySpears;
}
private List<String> spellings;
private BritnetSpearsSpellings() {
}
public List<String> getSpellings() {
return spellings;
}
}
@Override
public Iterator<String> iterator() {
return spellings.iterator();
}
public class Usage {
public static void main(String[] args) {
for (String sepllin : BritnetSpearsSpellings.of("Brittany Spears", "Brittney Spears", "Britany Spears"))
System.out.printf("You spel Britni like so: %s%n", sepllin);
}
}
}
class BritnetSpearsSpellings implements Iterable<String> {
public static BritnetSpearsSpellings of(String... spellings) {
BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings();
britneySpears.spellings = ImmutableList.copyOf(spellings);
return britneySpears;
}
private ImmutableList<String> spellings;
private BritnetSpearsSpellings() {
}
public ImmutableList<String> getSpellings() {
return spellings;
}
@Override
public Iterator<String> iterator() {
return spellings.iterator();
}
}
class BritnetSpearsSpellings implements Iterable<String> {
public static BritnetSpearsSpellings of(String... spellings) {
BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings(ImmutableList.copyOf(spellings));
return britneySpears;
}
private final ImmutableList<String> spellings;
private BritnetSpearsSpellings(ImmutableList<String> spellings) {
this.spellings = spellings;
}
public ImmutableList<String> getSpellings() {
return spellings;
}
@Override
public Iterator<String> iterator() {
return spellings.iterator();
}
}
请帮助我选择其中一种实施方式,并根据您的选择进行推理。
我认为方法#2的主要缺点是客户需要具备专门的 ImmutableList<E> 类型的认知/可见性,可能他们不应该这样做?
答案 0 :(得分:3)
显然,#3是我认为的最佳选择。 final
强制执行并记录该类(该字段)的不变性,而不仅仅是List
本身不可变的事实。
是否在getter中公开了List
一些javadoc或一个实际的ImmutableList
是另一回事。我已经看到了明确返回ImmutableList
文档意图的意见,但是,你仍然将自己绑定到一个实现而不是一个低级别的接口,并且可能需要在将来进行更改(即使不变性“通常”很好)。因此,对于您的应用程序而言,它不仅仅是一个用例的全局设计选择。如果您使用ImmutableList
,我认为这对客户来说不是一个真正的问题,名称是明确的,可以通过IDE轻松看出它是List
的实现,他们可以如果他们想要更多信息,请访问javadoc。谁知道,他们可能会喜欢它并开始使用它,与番石榴提供的所有其他好东西: - )
答案 1 :(得分:1)
从您的问题陈述(“对于给定的一组字符串应该只有一个类”),听起来您真正想要的是Interner<ImmutableSet<String>>
。
Interners.newStrongInterner()
),用于确保您只有一个具有任何给定数据的对象实例。或者,您可能需要查看Cache<ImmutableSet<String>>
(有关详细信息,请参阅Caches Explained)。
答案 2 :(得分:0)
我会使用Attempt #2
而不是Attempt #1
,因为它会记录您始终返回ImmutableList实例。通常,选择尽可能具体的返回类型和尽可能通用的参数类型很有用。但是对于这两种情况,更喜欢接口而不是具体类。
嗯,ImmutableList
是一个抽象类而不是接口。但由于它的性质,它的行为非常像界面。
Attempt #3
无法更改对象的生命周期和/或您希望整个类本身不可变时, spellings
是有意义的。否则,在对象生命周期内可以将spellings
分配给另一个ImmutableList,那么它就没有意义。
鉴于您的示例中的用例,我倾向于说#3是最佳选择。