Передайте объект в качестве параметра и внесите его в метод

Скажем, у меня есть Map<String, String>, и я хочу удалить все записи, которые содержат foo. Каков наилучший способ сделать это с точки зрения оптимизации/памяти и т.д.? Следующие четыре syso печатают тот же результат, то есть {n2=bar}.

public static void main(String[] args) {

    Map<String, String> in = new HashMap<String, String>();
    in.put("n1", "foo");
    in.put("n2", "bar");
    in.put("n3", "foobar");

    // 1- create a new object with the returned Map
    Map<String, String> in1 = new HashMap<String, String>(in);
    Map<String, String> out1 = methodThatReturns(in1);
    System.out.println(out1);

    // 2- overwrite the initial Map with the returned one 
    Map<String, String> in2 = new HashMap<String, String>(in);
    in2 = methodThatReturns(in2);
    System.out.println(in2);

    // 3- use the clear/putAll methods
    Map<String, String> in3 = new HashMap<String, String>(in);
    methodThatClearsAndReadds(in3);
    System.out.println(in3);

    // 4- use an iterator to remove elements
    Map<String, String> in4 = new HashMap<String, String>(in);
    methodThatRemoves(in4);
    System.out.println(in4);

}

public static Map<String, String> methodThatReturns(Map<String, String> in) {
    Map<String, String> out = new HashMap<String, String>();
    for(Entry<String, String> entry : in.entrySet()) {
        if(!entry.getValue().contains("foo")) {
            out.put(entry.getKey(), entry.getValue());
        }
    }
    return out;
}

public static void methodThatClearsAndReadds(Map<String, String> in) {
    Map<String, String> out = new HashMap<String, String>();
    for(Entry<String, String> entry : in.entrySet()) {
        if(!entry.getValue().contains("foo")) {
            out.put(entry.getKey(), entry.getValue());
        }
    }
    in.clear();
    in.putAll(out);
}

public static void methodThatRemoves(Map<String, String> in) {
    for(Iterator<Entry<String, String>> it = in.entrySet().iterator(); it.hasNext();) {
        if(it.next().getValue().contains("foo")) {
            it.remove();
        }
    }
}

Ответ 1

Лучший способ - methodThatRemoves, потому что:

  • С точки зрения потребления памяти: он не создает новую карту, поэтому не увеличивает накладные расходы памяти.
  • В терминах использования ЦП: итератор имеет сложность O (1) для вызова следующего или удаления текущего элемента.

Ответ 2

Самый эффективный способ methodThatRemoves, потому что он

  • Использование почти не памяти
  • Не создает объектов, кроме (легкого) итератора
  • Очень быстро (не использует поиск по карте)

Я бы не сделал копию сначала, хотя, если у вас нет немодифицируемой карты или вам нужно сохранить оригинал.

Ответ 3

Для меня лучше всего использовать метод Iterator --ThatRemoves, потому что вы не создаете промежуточную карту и не используете метод put.

Кстати, первая: methodThatReturns может быть быстрее, потому что put сложность - это O (1), тогда как удаление в O случае (O) в худшем случае, но будет использовать больше памяти, потому что у вас есть два разных экземпляра карты.

Ответ 4

Я бы лично пошел с methodThatRemoves, потому что вы выполняете только операцию цикла и проверяете равенство "foo". Другие делают это, а также создают карту объектов и отображают операции с ямой/положением. Таким образом, у вас явно есть один метод, делающий меньше.

Также, если вы хотите уменьшить использование памяти, вам лучше не создавать дополнительную HashMap, чтобы удалить одну или несколько записей. Это предполагает, что вы не против дополнительных вычислений для итерации карты.

Если вы действительно хотите углубиться, вы должны оценить это, используя профайлер или какой-то вид.