我想知道是否有一个地图的实现是:
简而言之,是否存在可以与Hash Maps进行性能比较的功能数据结构?
考虑这个简化的应用领域:
Person 是参与调查的任何人Report 是调查的一部分信息Report引用主要Person(调查的主题)Report具有次要相关的共犯(并且在其他调查或报告中肯定是主要的如果这些存储在某种数据库中并且我希望使用不可变对象,则似乎存在关于状态和引用的问题.
假设我改变了一些关于a的元数据Person.由于我的Person对象是不可变的,我可能会有一些代码:
class Person(
val id:UUID,
val aliases:List[String],
val reports:List[Report]) {
def addAlias(name:String) = new Person(id,name :: aliases,reports)
}
Run Code Online (Sandbox Code Playgroud)
因此,我Person的新别名成为一个新对象,也是不可变的.如果a Report指的是那个人,但别名在系统的其他地方被改变了,我Report现在指的是"老"人,即没有新别名的人.
同样,我可能会:
class Report(val id:UUID, val content:String) {
/** Adding more info to our report */
def updateContent(newContent:String) = new Report(id,newContent)
}
Run Code Online (Sandbox Code Playgroud)
由于这些对象不知道是谁引用它们,因此我不清楚如何让所有"引用者"知道有一个新对象可用来代表最近的状态.
这可以通过让所有对象从中央数据存储"刷新"并且创建新的,更新的对象的所有操作存储到中央数据存储来完成,但这感觉就像是对基础语言的引用的简洁重新实现.也就是说,让这些"次要可存储物体"变得可变更为明确.因此,如果我向a添加别名Person,则所有引用者都会看到新值而不执行任何操作.
当我们想要避免可变性时,如何解决这个问题,或者这是不可变性无效的情况?
在Scala我希望能够写
val petMap = ImmutableMultiMap(Alice->Cat, Bob->Dog, Alice->Hamster)
Run Code Online (Sandbox Code Playgroud)
底层Map [Owner,Set [Pet]]应该同时具有Map和Set不可变.这是ImmutibleMultiMap与伴随对象的初稿:
import collection.{mutable,immutable}
class ImmutableMultiMap[K,V] extends immutable.HashMap[K,immutable.Set[V]]
object ImmutableMultiMap {
def apply[K,V](pairs: Tuple2[K,V]*): ImmutableMultiMap[K,V] = {
var m = new mutable.HashMap[K,mutable.Set[V]] with mutable.MultiMap[K,V]
for ((k,v) <- pairs) m.addBinding(k,v)
// How do I return the ImmutableMultiMap[K,V] corresponding to m here?
}
}
Run Code Online (Sandbox Code Playgroud)
你能优雅地解决评论线吗?地图和集合都应该是不可变的.
谢谢!
我有一个关于Java内存模型的问题.这是一个介绍问题的简单类:
public class ImmutableIntArray {
private final int[] array;
public ImmutableIntArray() {
array = new int[10];
for (int i = 0; i < 10; i++) {
array[i] = i;
}
}
// Will always return the correct value?
public int get(int index) {
return array[index];
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,JMM保证在构造之后其他线程可以看到最终字段的值.但是我希望确保其他线程在构建之后能够看到存储在数组中的最新数据版本.
当然上面的代码只是一个呈现问题的简单示例,实际上我想为直接字节缓冲区实现一个简单的缓存,我不想依赖一些Collection类.目前我正在使用ReentrantReadWriteLock来确保正确的行为,但如果可能的话我想避免它.
java concurrency immutability thread-safety java-memory-model
我发现了一个我可以理解的可变集的奇怪行为:
我有一个对象,我想添加到一个集合.该类的equals方法被覆盖.当我向set添加两个不同的对象时,它为equals方法产生相同的输出,我在contains方法的可变和不可变集之间得到了不同的行为.
这是代码片段:
class Test(text:String){
override def equals(obj:Any) = obj match {
case t: Test => if (t.text == this.text) true else false
case _ => false
}
override def toString = text
}
val mutableSet:scala.collection.mutable.Set[Test] = scala.collection.mutable.Set.empty
mutableSet += new Test("test")
println(mutableSet)
println(mutableSet.contains(new Test("test")))
val immutableSet:scala.collection.immutable.Set[Test] = scala.collection.immutable.Set.empty
immutableSet += new Test("test")
println(immutableSet)
println(immutableSet.contains(new Test("test")))
Run Code Online (Sandbox Code Playgroud)
这产生了输出:
Set(test)
false
Set(test)
true
Run Code Online (Sandbox Code Playgroud)
在我看来,contains的两个调用应该产生相同的输出(true).
任何人都可以帮助我理解这里的区别,或者这是scala不可变集实现中的错误吗?顺便说一句,我使用scala 2.8.1.final
谢谢.
我对修改元组成员有点困惑.以下不起作用:
>>> thing = (['a'],)
>>> thing[0] = ['b']
TypeError: 'tuple' object does not support item assignment
>>> thing
(['a'],)
Run Code Online (Sandbox Code Playgroud)
但这确实有效:
>>> thing[0][0] = 'b'
>>> thing
(['b'],)
Run Code Online (Sandbox Code Playgroud)
还有效:
>>> thing[0].append('c')
>>> thing
(['b', 'c'],)
Run Code Online (Sandbox Code Playgroud)
不起作用,并且有效(嗯?!):
>>> thing[0] += 'd'
TypeError: 'tuple' object does not support item assignment
>>> thing
(['b', 'c', 'd'],)
Run Code Online (Sandbox Code Playgroud)
看似与以前相同,但有效:
>>> e = thing[0]
>>> e += 'e'
>>> thing
(['b', 'c', 'd', 'e'],)
Run Code Online (Sandbox Code Playgroud)
那么,当你能够并且不能修改元组内的某些内容时,游戏的规则到底是什么?它似乎更像禁止使用赋值成员的赋值运算符,但最后两个案例让我感到困惑.
为什么在Rust中强制使用不变性,除非你指定mut?这是安全性的设计选择吗,您是否认为它在其他语言中应该如何自然?
我应该澄清一下,我还是Rust的新手.那么这是一种与该语言中的另一个功能相关的设计选择吗?
在检查Java BigDecimal类的源代码时,我很惊讶它没有被声明为final class:
类BigDecimal
Run Code Online (Sandbox Code Playgroud)public class BigDecimal extends Number implements Comparable<BigDecimal>不可变的,任意精度的带符号十进制数.
(来自Oracle Docs)
是否有特定原因或开发人员忘记添加该关键字?不将不可变类声明为final是不错的做法?
同样的情况也适用BigInteger,但不是String宣布为最终的.
我对Haskell中不可变变量的概念很困惑.看来我们无法改变Haskell中变量的值.但是当我尝试在GHCI中使用代码时,似乎变量的值确实发生了变化:
Prelude> foo x=x+1
Prelude> a=1
Prelude> a
1
Prelude> foo a
2
Prelude> a=2
Prelude> a
2
Prelude> foo a
3
Run Code Online (Sandbox Code Playgroud)
这与不可变变量的想法有冲突吗?
非常感谢!