Как удалить дублирование из моего кода
У меня есть два подобных методов. Один из них что-то печатает, а другой что-то сохраняет. Как вы можете видеть есть много повторяющегося кода. Как я должен рефакторинг и убрать это дублирование ?
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;
}
обновление:
код был обновлен для решения проблемы, когда метод не совсем похож
3 ответов
универсальное действие интерфейса, которое имеет действие метода (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#, это похоже на lambdas.
edit:
использование анонимной типа:
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
}
}
}
предполагая, в каком порядке println
of "aaa"
и "bbb"
appear не имеет значения, вы можете заменить реализацию 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());
}
}
на языке программирования с первоклассными функциями вы передадите функцию в качестве параметра, указывающего, что вы хотите сделать внутри цикла (например, см. обновление ниже). Java будет иметь lambdas в версии 8, но они не совсем подходят для этой работы.
в текущем состоянии Java вам придется довольствоваться чем - то более уродливым-например, передачей дополнительного параметра методу; или вы можете передать анонимные внутренние классы, которые реализуют интерфейс, но ИМХО это еще уродливее, чем то, что я собираюсь предложить:
static void printSomething(List<String> list, boolean print)
если print
is 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;
}
обновление
например, в 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'}