Я использую его для реализации кэша, где неиспользованные записи автоматически собраны "мусор":
class Cache<TKey,TValue> : IEnumerable<KeyValuePair<TKey,TValue>>
{ Dictionary<TKey,WeakReference> dict = new Dictionary<TKey,WeakReference>();
public TValue this[TKey key]
{ get {lock(dict){ return getInternal(key);}}
set {lock(dict){ setInteral(key,value);}}
}
void setInteral(TKey key, TValue val)
{ if (dict.ContainsKey(key)) dict[key].Target = val;
else dict.Add(key,new WeakReference(val));
}
public void Clear() { dict.Clear(); }
/// <summary>Removes any dead weak references</summary>
/// <returns>The number of cleaned-up weak references</returns>
public int CleanUp()
{ List<TKey> toRemove = new List<TKey>(dict.Count);
foreach(KeyValuePair<TKey,WeakReference> kv in dict)
{ if (!kv.Value.IsAlive) toRemove.Add(kv.Key);
}
foreach (TKey k in toRemove) dict.Remove(k);
return toRemove.Count;
}
public bool Contains(string key)
{ lock (dict) { return containsInternal(key); }
}
bool containsInternal(TKey key)
{ return (dict.ContainsKey(key) && dict[key].IsAlive);
}
public bool Exists(Predicate<TValue> match)
{ if (match==null) throw new ArgumentNullException("match");
lock (dict)
{ foreach (WeakReference weakref in dict.Values)
{ if ( weakref.IsAlive
&& match((TValue) weakref.Target)) return true;
}
}
return false;
}
/* ... */
}
Поверьте мне; вам не нужно прозрачное преобразование туда и обратно. Это именно то, что пытались сделать функции scala.collection.jcl.Conversions
. На практике это вызывает много головной боли.
Корень проблемы с этим подходом заключается в том, что Scala автоматически вводит неявные преобразования по мере необходимости, чтобы вызов метода работал. Это может иметь очень печальные последствия. Например:
import scala.collection.jcl.Conversions._
// adds a key/value pair and returns the new map (not!)
def process(map: Map[String, Int]) = {
map.put("one", 1)
map
}
Этот код не будет полностью неуместным для тех, кто плохо знаком с фреймворком коллекций Scala или даже с концепцией неизменяемых коллекций. К сожалению, это совершенно неверно. Результатом этой функции является такая же карта . Вызов put
запускает неявное преобразование в java.util.Map
, который с радостью принимает новые ценности и быстро отбрасывается. Исходная карта
не изменена (поскольку она действительно неизменна).
Хорхе Ортис выразился лучше всего, когда говорит, что вы должны определять неявные преобразования только для одной из двух целей:
A
и B
, которые не связаны между собой. Вы можете определить преобразование A => B
if и только , если вы предпочитаете иметь A <: B
( <:
означает «подтип»). Начиная с java.util. Карта
, очевидно, не новый тип, не связанный ни с чем в нашей иерархии, мы не можем подпадать под первую оговорку. Таким образом, наша единственная надежда состоит в том, что наше преобразование Map [A, B] => java.util.Map [A, B]
будет подходить для второго. Однако для Scala Map
совершенно бессмысленно наследовать от java.util.Map
. Это действительно полностью ортогональные интерфейсы / черты. Как показано выше, попытка игнорировать эти рекомендации почти всегда приводит к странному и неожиданному поведению.
На самом деле методы javautils asScala
и asJava
были разработаны для решения этой точной задачи. проблема. Существует неявное преобразование (на самом деле их несколько) в javautils из Map [A, B] => RichMap [A, B]
. RichMap
- это совершенно новый тип, определенный javautils, поэтому его единственная цель - добавить элементы в Map
. В частности, он добавляет метод asJava
, который возвращает карту-оболочку, которая реализует java.util.Map
и делегирует исходный экземпляр Map
. Это делает процесс более явным и гораздо менее подверженным ошибкам.
Другими словами, использование asScala
и asJava
является наилучшей практикой. Пройдя оба этих пути независимо в производственном приложении, я могу из первых рук сказать вам, что подход javautils намного безопаснее и с ним проще работать. Не пытайтесь обойти его защиту только ради спасения 8 персонажей!
Map
. В частности, он добавляет метод asJava
, который возвращает карту-оболочку, которая реализует java.util.Map
и делегирует исходный экземпляр Map
. Это делает процесс более явным и гораздо менее подверженным ошибкам.
Другими словами, использование asScala
и asJava
является наилучшей практикой. Пройдя оба этих пути независимо в производственном приложении, я могу из первых рук сказать вам, что подход javautils намного безопаснее и с ним проще работать. Не пытайтесь обойти его защиту только ради спасения 8 персонажей!
Map
. В частности, он добавляет метод asJava
, который возвращает карту оболочки, которая реализует java.util.Map
и делегирует исходный экземпляр Map
. Это делает процесс более явным и гораздо менее подверженным ошибкам.
Другими словами, использование asScala
и asJava
является наилучшей практикой. Пройдя оба этих пути независимо в производственном приложении, я могу из первых рук сказать вам, что подход javautils намного безопаснее и с ним проще работать. Не пытайтесь обойти его защиту только ради спасения 8 персонажей!
java.util.Map
и делегирует исходный экземпляр Map
. Это делает процесс более явным и гораздо менее подверженным ошибкам.
Другими словами, использование asScala
и asJava
является наилучшей практикой. Пройдя оба этих пути независимо в производственном приложении, я могу из первых рук сказать вам, что подход javautils намного безопаснее и с ним проще работать. Не пытайтесь обойти его защиту только ради спасения 8 персонажей!
java.util.Map
и делегирует исходный экземпляр Map
. Это делает процесс более явным и гораздо менее подверженным ошибкам.
Другими словами, использование asScala
и asJava
является наилучшей практикой. Пройдя оба этих пути независимо в производственном приложении, я могу из первых рук сказать вам, что подход javautils намного безопаснее и с ним проще работать. Не пытайтесь обойти его защиту только ради спасения 8 персонажей!
asScala
и asJava
является наилучшей практикой. Пройдя оба этих пути независимо в производственном приложении, я могу из первых рук сказать вам, что подход javautils намного безопаснее и с ним проще работать. Не пытайтесь обойти его защиту только ради спасения 8 персонажей! использование asScala
и asJava
является наилучшей практикой. Пройдя оба этих пути независимо в производственном приложении, я могу из первых рук сказать вам, что подход javautils намного безопаснее и с ним проще работать. Не пытайтесь обойти его защиту только ради спасения 8 персонажей! Вот несколько быстрых примеров использования библиотеки Scalaj-collection Хорхе Ортиса :
import org.scala_tools.javautils.Implicits._
val sSeq = java.util.Collections.singletonList("entry") asScala
// sSeq: Seq[String]
val sList = sSeq toList // pulls the entire sequence into memory
// sList: List[String]
val sMap = java.util.Collections.singletonMap("key", "value") asScala
// sMap: scala.collection.Map[String, String]
val jList = List("entry") asJava
// jList: java.util.List[String]
val jMap = Map("key" -> "value") asJava
// jMap: java.util.Map[String, String]