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

更新:

当方法不完全相似时,代码已更新以解决问题

4

3 回答 3

7

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());
  }
}
于 2013-04-23T13:57:19.637 回答
3

具有方法 action(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 种不同的 Action 实现。

如果您不想创建类,可以使用匿名类型。

如果你知道 c#,这类似于 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
        }
    }

}
于 2013-04-23T14:02:22.763 回答
2

在具有一流函数的编程语言中,您将传递一个函数作为参数,指示您想要在循环内执行的操作(例如,请参见下面的更新)。Java 将在版本 8 中包含 lambda,但它们并不能胜任这项工作。

在 Java 的当前状态下,您将不得不接受一些更丑陋的事情——例如,向方法传递一个额外的参数;或者您可以传递实现接口的匿名内部类,但恕我直言,这比我将要建议的更丑陋:

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

如果printtrue则在循环内打印,否则添加到Map. 当然,您必须if在循环内添加几个 s 来检查这个条件,并且在开始时,额外添加一个if来确定是否Map要初始化 s。无论哪种方式,该方法都返回 a 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'}
于 2013-04-23T13:55:55.713 回答