Подтвердить что ты не робот

Как удалить дублирование из моего кода

У меня есть два похожих метода. Один из них печатает что-то, и один из них спасает что-то. Как вы можете видеть, существует много дублирующего кода. Как мне его реорганизовать и удалить это дублирование?

public static void printSomething(List<String> list) {
    for (String item : list) {
        if (item.contains("aaa")) {
            System.out.println("aaa" + item);
        }
        if (item.contains("bbb")) {
            System.out.println("bbb" + item);
        } else {
            System.out.println(item);
        }
    }
}

public static Map<String, String> getSomething(List<String> list) {
    Map<String, String> map = new HashMap<String, String>();
    for (String item : list) {
        if (item.contains("aaa")) {
            map.put("aaa", item);
        }
        if (item.contains("bbb")) {
            map.put("bbb", item);
        } else {
            //do nothing
        }
    }
    return map;
}

UPDATE:

Код обновлен, чтобы решить проблему, когда метод не совсем похож.

4b9b3361

Ответ 1

Общее действие интерфейса, которое имеет действие метода (T t), может уменьшить код.

public interface Action<E> {
        void action(E e);
}

Пример:

public static void forEach(List<String> list, Action <String> action) {
    for(String s : list){
           action.action(s);

}

Теперь вам нужно всего две различные реализации Action.

Вы можете использовать анонимные типы, если вы не хотите создавать класс.

Если вы знаете С#, это похоже на lambdas.

изменить:

Использование анонимного типа:

public static Map<String, String> getSomething(List<String> list) {
    final Map<String, String> map = new HashMap<String, String>();
    forEach(list, new Action<String>() {
        @Override
        public void action(String e) {
            if (e.contains("aaa")) {
                map.put("aaa", e);
            }
            if (e.contains("bbb")) {
                map.put("bbb", e);
            } else {
                // do nothing
            }
        }
    });
    return map;
}

Создание класса:

public static Map<String, String> getSomething2(List<String> list) {
    final Map<String, String> map = new HashMap<String, String>();
    forEach(list, new ListToMapAction(map));
    return map;
}


public class ListToMapAction implements Action<String> {

    Map<String, String> map;

    public ListToMapAction(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public void action(String e) {
        if (e.contains("aaa")) {
            map.put("aaa", e);
        }
        if (e.contains("bbb")) {
            map.put("bbb", e);
        } else {
            // do nothing
        }
    }

}

Ответ 2

Предполагая, что порядок, на который отображаются println of "aaa" и "bbb", не имеет значения, вы можете заменить реализацию printSomething на

public static void printSomething(List<String> list) {
  Map<String, String> map = getSomething(list);
  for(Map.Entry<String, String> entry : map) {
    System.out.println(entry.getKey() + entry.getValue());
  }
}

Ответ 3

На языке программирования с первоклассными функциями вы передадите функцию как параметр, указывающий, что вы хотите делать внутри цикла (например, см. обновление ниже). Java будет иметь lambdas в версии 8, но они не совсем подходят для работы.

В текущем состоянии Java вам придется решить что-то более уродливое - например, передав дополнительный параметр методу; или вы можете обойти анонимные внутренние классы, которые реализуют интерфейс, но IMHO, который даже уродливее, чем то, что я собираюсь предложить:

static void printSomething(List<String> list, boolean print)

Если print - true, тогда напечатайте внутри цикла, иначе добавьте в Map. Конечно, вам нужно будет добавить пару if внутри цикла для проверки этого условия и в начале один дополнительный if, чтобы определить, будет ли инициализироваться Map. В любом случае метод возвращает Map, но Map может быть null для случая печати. Вот что я имею в виду:

static Map<String, String> processSomething(List<String> list, boolean print) {

    Map<String, String> map = null;
    if (!print)
        map = new HashMap<String, String>();

    for (String item : list) {
        if (item.contains("aaa")) {
            if (print)
                System.out.println("aaa" + item);
            else
                map.put("aaa", item);
        }
        if (item.contains("bbb")) {
            if (print)
                System.out.println("bbb" + item);
            else
                map.put("bbb", item);
        } else if (print) {
            System.out.println(item);
        }
    }

    return map;

}

UPDATE

Например, в Python, который позволяет передавать функции в качестве параметров, так вы решите проблему в элегантном стиле:

def processSomething(lst, func):
    result = None
    for item in lst:
        if 'aaa' in item:
            result = func(item, 'aaa', result)
        elif 'bbb' in item:
            result = func(item, 'bbb', result)
        else:
            result = func(item, '', result)
    return result

def printer(item, key, result):
    print key + item

def mapper(item, key, result):
    if not result:
        result = {}
    if key:
        result[key] = item
    return result

Посмотрите, как это работает:

processSomething(['aaa', 'bbb', 'ccc'], printer)
=> aaaaaa
   bbbbbb
   ccc

processSomething(['aaa', 'bbb', 'ccc'], mapper)
=> {'aaa': 'aaa', 'bbb': 'bbb'}