2013-04-23 2 views
11

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

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:

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

+0

Это зависит ... почему у вас есть эти 2 метода ... вы можете поделиться вызывающие методы – Frank

+0

Возможно, вы можете использовать возвращаемое значение 'getSomething()' для выполнения распечаток в 'printSomething()'; Я пошел бы так, чтобы избежать методов, возвращающих ничего (которые не являются сеттерами c). – adrianp

+0

@HighPerformanceMark извините за ошибку. Я имею в виду дублирование – hudi

ответ

3

родовое Action Interface, которые имеют способ действия (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); 

} 

Теперь вам просто нужно 2 различных реализаций действий.

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

Если вы знаете C#, это похоже на лямбда.

редактировать:

Использование annonymous Тип:

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 
     } 
    } 

} 
+0

извините, но я не понимаю ваш пример. Ваш метод не возвращает ничего, как мне получить мою карту? – hudi

+0

отредактирован с полной реализацией –

+0

когда вы только что-то напечатали? Я думаю, что будет еще некоторое дублирование в методе метода – hudi

2

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

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

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

Если print является true затем распечатать внутри цикла, в противном случае добавить к Map. Конечно, вам нужно добавить пару if s внутри цикла для проверки этого условия, а в начале - один дополнительный 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'} 
+3

Это очень уродливый пример. Имя этого метода печатает или получает? Во-вторых, у вас все еще есть пустота, поэтому вы ничего не возвращаете. – hudi

+0

Название может быть чем-то общим. И метод должен возвращать карту всегда, даже если она равна нулю. –

+0

Хороший совет. И вы всегда можете передать реализацию интерфейса - шаблон делегата. –

7

Ассу мина порядок которого println из "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()); 
    } 
} 
+0

+1. Это предполагает, что порядок распечаток не имеет значения. – Keppil

+0

Справа - я хотел написать это, спасибо, что указал на это. – tehlexx

+0

hm thx это будет работать, если метод будет таким же, но что если печать будет содержать: ... else {System.out.println ("bbb" + item); } и получить ... else {// doNothing} – hudi

Смежные вопросы