Задаване на еквивалент на WeakHashMap?

HashSet<WeakReference<T>> Set еквивалент ли е на WeakHashMap<T>? Тоест, записите ще бъдат ли автоматично изтрити, когато вече няма препратки към тях?

Ако не, какъв е еквивалентът?


person Barry Fruitman    schedule 14.10.2013    source източник
comment
Повярвайте, че това е, което може би търсите: stackoverflow.com/a/4062950/717932   -  person dardo    schedule 14.10.2013
comment
възможен дубликат на Защо съществува WeakHashMap, но липсва WeakSet?   -  person Oliver Charlesworth    schedule 14.10.2013
comment

Ако необходимостта от такава функционалност е само за този единствен клас, моят съвет е да изберете второто решение, което споменахте, като използвате отговора на Nsh.

В противен случай, ако този проблем възникне на няколко места във вашия проект, ето решение, което измислих:

class YourClass(MutexInit):
    """First of all inherit the MutexInit class by..."""

    def __init__(self, **kwargs):
        """...calling its __init__ at the end of your own __init__. Then..."""
        super(YourClass, self).__init__(**kwargs)

    @sub_init
    def _init_foo_bar(self, foo, bar):
        """...just decorate each sub-init method with @sub_init"""
        self.baz = foo + bar

    @sub_init
    def _init_bar_baz(self, bar, baz):
        self.foo = bar - baz

Това ще направи кода ви по-четлив и ще скриете грозните детайли зад тези декоратори, които се обясняват сами по себе си.

Забележка: Можем също така да елиминираме декоратора @sub_init, но мисля, че това е единственият законен начин за маркиране на метода като подинициализация. В противен случай вариант би бил да се съгласите да поставите префикс преди името на метода, да речем _init, но мисля, че това е лоша идея.

Ето имплементациите:

import inspect


class MutexInit(object):
    def __init__(self, **kwargs):
        super(MutexInit, self).__init__()

        for arg in kwargs:
            setattr(self, arg, kwargs.get(arg))

        self._arg_method_dict = {}
        for attr_name in dir(self):
            attr = getattr(self, attr_name)
            if getattr(attr, "_isrequiredargsmethod", False):
                self._arg_method_dict[attr.args] = attr

        provided_args = tuple(sorted(
            [arg for arg in kwargs if kwargs[arg] is not None]))
        sub_init = self._arg_method_dict.get(provided_args, None)

        if sub_init:
            sub_init(**kwargs)
        else:
            raise AttributeError('Insufficient arguments')


def sub_init(func):
    args = sorted(inspect.getargspec(func)[0])
    self_arg = 'self'
    if self_arg in args:
        args.remove(self_arg)

    def wrapper(funcself, **kwargs):
        if len(kwargs) == len(args):
            for arg in args:
                if (arg not in kwargs) or (kwargs[arg] is None):
                    raise AttributeError
        else:
            raise AttributeError

        return func(funcself, **kwargs)
    wrapper._isrequiredargsmethod = True
    wrapper.args = tuple(args)

    return wrapper
  -  person Barry Fruitman    schedule 15.10.2013


Отговори (1)


Не, ако даден обект, посочен от един от WeakReferences в набора, бъде събран, WeakReference пак ще бъде включен в набора и няма да бъде премахнат автоматично, но техният referent ще бъде null. WeakHashMap използва допълнителен код за премахване на слабо реферираните ключове от картата, когато се събират боклуци.

Набор еквивалент на WeakHashMap е:

Set<T> set = Collections.newSetFromMap(new WeakHashMap<T, Boolean>()); 

Като HashSet също използва HashMap вътрешно.

BTW: WeakReference е просто обект, сочещ към обект, който може да бъде събран боклук въпреки препратката, поддържана от WeakReference. Самият WeakReference няма да бъде събиран за боклук, докато не бъде вече строго споменат никъде, както всички други обекти.

person Njol    schedule 15.10.2013
comment
Това е отговорът, който търсех. Благодаря ти! - person Barry Fruitman; 16.10.2013