11

私は2つの同様の方法を持っています。そのうちの 1 つは何かを印刷し、そのうちの 1 つは何かを保存します。ご覧のとおり、多くの重複コードがあります。リファクタリングしてこの重複を削除するにはどうすればよいですか?

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

printlnof"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());
  }
}
于 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);

}

これで、Action の 2 つの異なる実装が必要になります。

クラスを作成したくない場合は、匿名型を使用できます。

C# を知っている場合、これはラムダに似ています。

編集:

匿名型の使用:

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 でラムダを使用する予定ですが、十分に機能しているとは言えません。

Java の現在の状態では、より醜い方法で解決する必要があります。たとえば、メソッドに余分なパラメーターを渡すなどです。または、インターフェイスを実装する匿名の内部クラスを渡すこともできますが、私が提案しているものよりもさらに醜いです:

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

の場合printtrueループ内で出力し、そうでない場合は に追加しますMap。もちろん、ifこの条件をチェックするためにループ内にいくつかの sを追加する必要があります。最初に、 が初期化されるifかどうかを判断するために 1 つの余分な s を追加する必要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'}
于 2013-04-23T13:55:55.713 に答える