我可以使用该方法创建一个GuavaImmutableListof,并根据传递的对象获取正确的泛型类型:
Foo foo = new Foo();
ImmutableList.of(foo);
Run Code Online (Sandbox Code Playgroud)
但是,没有参数的of方法无法推断泛型类型并创建ImmutableList<Object>.
如何创建一个ImmutableList满足的空List<Foo>?
当我们使用数组创建列表时java.util.Arrays.asList(),列表是不可变的.我很想知道为什么我们想要创建一个不可变列表,当List(Set或Map)的基本目的是具有动态大小并且能够随意添加,删除元素时.当我们需要一个固定大小的数据结构,我们去阵列,当我们需要一个动态的数据结构,我们去List或Set或Map等.那么,什么是具有不可变列表的目的是什么?我在完成任务时遇到了这个问题.
在不可变性之前,IEnumerable是许多API中的首选接口,因为它具有API对传递对象的实际类型不敏感的优点.
public void DoSomeEnumerationsWithACollection(IEnumerable<Thing> collectionOfThings)
{
foreach (var thing in collectionOfThings) doSomethingWith(thing);
foreach (var thing in collectionOfThings) doSomethingElseWith(thing);
}
Run Code Online (Sandbox Code Playgroud)
当然,至少有两个缺点:
API背后的代码不能依赖collectionOfThings的不变性,可能会遇到"集合修改"异常或遇到其他其他微妙问题.
我们不知道collectionOfThings是真实集合还是简单的延迟查询.如果我们假设它是一个真正的集合,那么我们就不会通过运行多个枚举来降低性能.如果我们假设它是一个延迟查询并且它实际上是一个真实的集合,那么将其转换为本地列表或其他冻结集合会产生不必要的成本,尽管它确实有助于保护我们免受第一个问题的影响(执行"ToList"操作时仍存在竞争条件).显然,我们可以编写少量代码来检查这一点,并尝试做"正确的事情",但这是令人讨厌的额外混乱.
我必须承认,除了使用命名约定之外,我从未找到过令人满意的模式来解决这个问题.尽管存在缺点,但是实用的方法似乎是IEnumerable是传递集合的最低摩擦方法.
现在,随着不可变的收藏,情况得到了很大改善......
public void DoSomeEnumerationsWithACollection(ImmutableList<Thing> collectionOfThings)
{
Run Code Online (Sandbox Code Playgroud)
不再存在收集修改的风险,并且对多个枚举的性能影响没有任何歧义.
但是,我们显然失去了API的灵活性,因为我们现在必须传入一个ImmutableList.如果我们的客户端有其他类型的可枚举不可变集合,则必须将其复制到ImmutableList中才能被使用,即使我们想要做的只是枚举它.
理想情况下,我们可以使用类似的界面
public void DoSomeEnumerationsWithACollection(IImmutableEnumerable<Thing> collectionOfThings)
Run Code Online (Sandbox Code Playgroud)
但是,当然,除了约定之外,接口不能强制执行不可变性等语义.
使用基类可能会起作用
public void DoSomeEnumerationsWithACollection(ImmutableEnumerableBase<Thing> collectionOfThings)
Run Code Online (Sandbox Code Playgroud)
除了它被认为是创建未密封的不可变类的不良形式,以免子类引入可变性.无论如何,这还没有在BCL中完成.
或者我们可以继续在API中使用IEnumerable并使用命名约定来明确我们的代码依赖于传递的不可变集合.
所以...我的问题是在传递不可变集合时哪些模式被认为是最好的?是ImmutableList "新的IEnumerable "一旦我们开始使用不可变性,或是否有更好的办法?
更新
IReadOnlyCollection(由Yuval Itzchakov建议)是对IEnumerable的明显改进,但仍然没有完全保护消费者免受集合中不受控制的变化的影响.值得注意的是,Roslyn代码库大量使用不变性(主要通过ImmutableArray)并且在将这些传递给其他方法时似乎使用显式类型,尽管有几个位置将ImmutableList传递给接受IEnumerable的方法.
我有一个Java/Kotlin互操作问题.一个Kotlin不可变列表被编译成一个可变的普通java.util.ArrayList!
Kotlin(图书馆):
class A {
val items: List<Item> = ArrayList()
}
Run Code Online (Sandbox Code Playgroud)
Java(消费者):
A a = new A();
a.getItems().add(new Item()); // Compiles and runs but I wish to fail or throw
Run Code Online (Sandbox Code Playgroud)
如何从Java角度使我的Kotlin类完全不可变?
ImmutableList从NuGet软件包Microsoft.Bcl.Immutable版本1.0.34以及1.1.22-beta中体验Microsoft的一些意外性能
从不可变列表中删除项目时,性能非常慢.对于ImmutableList包含20000个整数值(1 ... 20000),如果开始从值20000移除到1,则从列表中删除所有项目大约需要52秒.如果我使用泛型List<T>,我在每次删除操作后创建列表的副本,它需要大约500毫秒.
我对这些结果感到有些惊讶,因为我认为这ImmutableList比复制仿制品更快List<T>,但也许这是可以预料的?
// Generic List Test
var genericList = new List<int>();
var sw = Stopwatch.StartNew();
for (int i = 0; i < 20000; i++)
{
genericList.Add(i);
genericList = new List<int>(genericList);
}
sw.Stop();
Console.WriteLine("Add duration for List<T>: " + sw.ElapsedMilliseconds);
IList<int> completeList = new List<int>(genericList);
sw.Restart();
// Remove from 20000 -> 0.
for (int i = completeList.Count - 1; i >= 0; i--)
{
genericList.Remove(completeList[i]);
genericList …Run Code Online (Sandbox Code Playgroud) 我不明白 Immutable JS List 的大小会如何增长。
正如官方文档https://facebook.github.io/immutable-js/docs/#/List/push上的示例所示,在不可变的 js 列表中推送某些内容将自动增加大小。
在我的代码中:
const list: List = List();
list.push(object);
console.log(list, list.size);
Run Code Online (Sandbox Code Playgroud)
我在控制台的输出是:
(1) object
length: 1
___proto___: Array(0)
undefined
Run Code Online (Sandbox Code Playgroud)
这与方面输出确实不同。没有大小,如果我在代码中使用长度 Typescript 告诉我列表中不存在“长度”。我将 React 与 Typescript 和 Immutable.JS 结合使用
有人知道会发生什么吗?
我想简化与ImmutableList.of()功能相关的现有代码
我曾经尝试通过消除“ new ...”构造函数来优化第二个List的创建,但是我当然不能通过调用.add()来扩展不可变列表。
当前代码:
static final ImmutableList<ProductCodeEnum> PRODUCTS = ImmutableList.of(ProductCodeEnum.A, ProductCodeEnum.B, ProductCodeEnum.C);
static final ImmutableList<ProductCodeEnum> PRODUCTS_EXTENDED_LIST = new ImmutableList.Builder<ProductCodeEnum>().addAll(PRODUCTS)
.add(ProductCodeEnum.D)
.add(ProductCodeEnum.E)
.build();
Run Code Online (Sandbox Code Playgroud)
预期的代码如下:
static final ImmutableList<ProductCodeEnum> PRODUCTS = ImmutableList.of(ProductCodeEnum.A, ProductCodeEnum.B, ProductCodeEnum.C);
static final ImmutableList<ProductCodeEnum> PRODUCTS_EXTENDED = PRODUCTS + ImmutableList.of(ProductCodeEnum.D, ProductCodeEnum.E);
Run Code Online (Sandbox Code Playgroud) 我有一段代码经常迭代一个小列表.鉴于列表在运行时期间永远不会更改,我将实现替换为ImmutableList<T>.通过dotTrace查看性能跟踪,这比正常情况要糟糕得多List<T>:
(List<T>左,ImmutableList<T>右)
为什么会发生这种情况并且有解决方法?
我正在使用Google的ImmutableList类http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableList.html
我正在寻找一个方法,它接受一个现有的ImmutableList和一个额外的元素(相同类型),并返回一个新的 ImmutableList包含旧元素加上新元素.
也许我在文档中遗漏了一些明显的东西?
如何在cpp中创建不可变列表?列表的引用及其数据应保持不变。
我不会在vector或任何其他容器上做包装器类(我知道与本文类似的方法)。
使用constexpr或进行此操作的最佳方法是什么const pointers?
immutablelist ×10
java ×5
immutability ×4
c# ×3
guava ×2
.net ×1
arrays ×1
c++ ×1
collections ×1
generics ×1
immutable.js ×1
kotlin ×1
list ×1
performance ×1
reactjs ×1
size ×1
typescript ×1