从Scala集合体系结构第3版“Scala编程”一书中运行PrefixMap示例,我不明白在调用update时更新继承的PrefixMap Map。 这是代码:
import collection._
class PrefixMap[T]
extends mutable.Map[String, T]
with mutable.MapLike[String, T, PrefixMap[T]] {
val id: Long = PrefixMap.nextId
var suffixes: immutable.Map[Char, PrefixMap[T]] = Map.empty
var value: Option[T] = None
def get(s: String): Option[T] =
if (s.isEmpty) value
else suffixes get s(0) flatMap (_.get(s substring 1))
def withPrefix(s: String): PrefixMap[T] =
if (s.isEmpty) this
else {
val leading = s(0)
suffixes get leading match {
case None =>
suffixes = suffixes + (leading -> empty)
case _ =>
}
val ret = suffixes(leading) withPrefix (s substring 1)
println("withPrefix: ends with: id="+this.id+", size="+this.size+", this="+this)
ret
}
override def update(s: String, elem: T) = {
println("update: this before withPrefix: id="+this.id+", size="+this.size+", return="+this)
val pm = withPrefix(s)
println("update: withPrefix returned to update: id="+pm.id+", size="+pm.size+", return="+pm)
println("===> update: this after withPrefix and before assignment to pm.value : id="+this.id+", size="+this.size+", return="+this)
pm.value = Some(elem)
println("===> update: this after assinment to pm.value: id="+this.id+", size="+this.size+", return="+this)
}
override def remove(s: String): Option[T] =
if (s.isEmpty) { val prev = value; value = None; prev }
else suffixes get s(0) flatMap (_.remove(s substring 1))
def iterator: Iterator[(String, T)] =
(for (v <- value.iterator) yield ("", v)) ++
(for ((chr, m) <- suffixes.iterator;
(s, v) <- m.iterator) yield (chr +: s, v))
def += (kv: (String, T)): this.type = { update(kv._1, kv._2); this }
def -= (s: String): this.type = { remove(s); this }
override def empty = new PrefixMap[T]
}
object PrefixMap {
var ids: Long = 0
def nextId: Long = { PrefixMap.ids+=1; ids }
}
object MyApp extends App {
val pm = new PrefixMap[Int]
pm.update("a", 0)
println(pm)
}
输出结果为:
更新:这在withPrefix之前:id = 1,size = 0,return = Map()
withPrefix:以:id = 1,size = 0,this = Map()
结束更新:withPrefix返回更新:id = 2,size = 0,return = Map()
===&GT;更新:这是在withPrefix之后和赋值给pm.value之前:id = 1,size = 0,return = Map()
===&GT;更新:这是对pm.value的暗示:id = 1,size = 1,return = Map(a - &gt; 0)
地图(a - &gt; 0)
所以问题是:更新方法中带有“pm.value = Some(elem)”的行怎么可能导致继承的PrefixMap Map用(a - &gt; 0)更新?
答案 0 :(得分:2)
“ 继承 PrefixMap地图”的含义尚不清楚。 Map
是trait
,如果您来自Java世界,则类似于interface
。这意味着Map
本身并不具有任何价值,它只是指定契约,并通过“核心”方法(您在PrefixMap
中实现的方法)提供各种便捷方法的默认实现。
至于整个数据结构的工作原理,您应该将此PrefixMap
实现假设为"tree"。逻辑上,每个边都有一个char(在前缀序列中),每个节点可能是一个值,该值对应于通过在从根到当前节点的路上累积所有字符而创建的字符串。
因此,如果您有一个带有"ab" -> 12
键值的Map,那么树将如下所示:
如果您将"ac" -> 123
添加到树中,它将变为
最后,如果您将"a" -> 1
添加到树中,它将变为:
这里重要的观察是,如果你将“a”节点作为根,你将留下的是一个有效的前缀树,所有字符串都用“a”前缀缩短。
在物理上,布局有点不同:
PrefixMap[T]
,它是来自外部的Map[String,T]
,也是一个空字符串密钥的节点。value
+ suffixes
的内部节点,即子节点的可选值和合并列表,其边缘对应的字符为Map[Char, PrefixMap[T]]
正如您所看到的,update
实施有效地找到withPrefix
调用的内容,然后为其分配值。那么withPrefix
方法的作用是什么?虽然它是递归实现的,但是以迭代的方式思考它可能更容易。从这个角度来看,它逐个遍历给定String
的字符,并在树中导航,创建缺少的节点,参见
case None =>
suffixes = suffixes + (leading -> empty)
并最终返回与整个String
对应的节点(即this
,以防最深的递归s.isEmpty
)
方法get
实现实际上与withPrefix
非常相似:它递归地迭代给定的字符串并在树中导航,但它更简单,因为它不必创建缺少的节点。由于子节点实际上也存储在Map
get
方法中,Option
方法返回PrefixMap
的方式与Option
应返回flatMap
的方式相同。所以你可以使用iterator
,如果在某个级别没有这样的子节点,它将正常工作。
最后value.iterator
将其迭代器创建为
Option
(幸运的是,Scala iterator
实现了iterator
,只返回1或0个元素,具体取决于是否有值)val pm = new PrefixMap[Int]
pm.update("a", 0)
println(pm)
只是添加自己的字符作为其键的前缀。所以当你这样做时
update
pm.toString
创建树中的节点并存储该值。 iterate
实际上使用value
来构建字符串表示。因此,它会在树集合中迭代所有节点中非空Option
List<?> chatList = chatService.limitedChatResult(eventStatus.getFlexiObject().getId(), 10, 10);
getLogger().info("chatList: " + chatList.size());
def sortedMap = [:];
List<Chat> dayChatEntries = null;
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
int x = 0;
getLogger().info("sortedMap before starting the loop: map --> " + sortedMap);
for(Chat chat: chatList){
String day = sdf.format(chat.getLastWrite());
if (sortedMap.containsKey(day)) {
getLogger().info(x + " day: " + day);
getLogger().info("sortedMap: " + sortedMap); //I can not print the map at this position
getLogger().info("sortedMap key: " + sortedMap[day]);
sortedMap.get(day).add(chat);
getLogger().info("a new chat object was added to map list");
} else {
getLogger().info(x + " day is not in the map: " + day);
dayChatEntries = new ArrayList<Chat>();
dayChatEntries.add(chat);
sortedMap.put(day, dayChatEntries);
getLogger().info("The day has been added! ");
}
x++;
}
的所有值。