Карта со строковым ключом и значением <T> - PullRequest
1 голос
/ 05 октября 2019

У меня есть список значений:

{("1", "3"), ("1", "5"), ("3", "13") ("5", "4"), ("1", "7"), ("8", "9"), ("9", "1"), ("1", "23"), ("5", "7")}

и фильтр, который должен применяться к каждому элементу "1: 3,3: 13,5: -". Мне нужно получить другой список со значениями, которые соответствуют с фильтром. В этом случае результат должен быть:

Значения: 1 3 Значения: 3 13 Значения: 5 4 Значения: 5 7

В фильтре это значение 5: - означает, что он соответствует первому элементу и не учитывает второе значение, поэтому любой элемент, начинающийся с 5, в порядке.

import java.util.*;
import java.util.Set;
import java.util.stream.Collectors;

class Filter {
    private String valueFilter1;
    private String valueFilter2;

    public Filter(String valueFilter1, String valueFilter2) {
        this.valueFilter1 = valueFilter1;
        this.valueFilter2 = valueFilter2;
    }

    public Filter(String fil) {
        String[] filResult = fil.split(":");
        this.valueFilter1 = filResult[0];
        this.valueFilter2 = filResult[1];
    }

    public String getValueFilter1() {
        return valueFilter1;
    }

    public String getValueFilter2() { return valueFilter2; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Filter that = (Filter) o;
        return Objects.equals(valueFilter1, that.valueFilter1) &&
                Objects.equals(valueFilter2, that.valueFilter2);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((valueFilter1 == null) ? 0 : valueFilter1.hashCode());
        result = prime * result + ((valueFilter2 == null) ? 0 : valueFilter2.hashCode());
        return result;
    }

}


public class FilterUtils {
    private static void filterMessages(List<Filter> eventsParam, String type) {

        Set<Filter> filter1 = new HashSet<>();
        Set<String> filter2 = new HashSet<>();

        Arrays.stream(type.split(","))
                .forEach(f -> {
                    if (f.contains("-"))
                        filter2.add(f.split(":")[0]);
                    else
                        filter1.add(new Filter(f));
                });

        // This following logic is in another method called processMessage().
        // So I'm trying to return both filters as in processMessage I have something like this:
        // .stream()
        //                .filter(e -> filterMessages(eventsParam).contains(new Filter(e.getValueFilter1(), e.getValueFilter2()))
        //                .collect(Collectors.toList());
        // the real method filterMessages only receives List<Filter> eventsParam as argument
        // I was thinking of returning a map of Set like this Map<String, Set<Object>> or Map<String, Set<T>> but it didn't work
        // map.put("filter1", filter1);
        // map.put("filter2", filter2);
        // Not sure how to make it work

        List<Filter> result = eventsParam
                .stream()
                .filter(e -> filter1.contains(new Filter(e.getValueFilter1(), e.getValueFilter2())) |
                             filter2.contains(e.getValueFilter1()))
                .collect(Collectors.toList());

        for (Filter r: result) {
            System.out.println("Values: " + r.getValueFilter1() + " " + r.getValueFilter2());
        }
    }



    public static void main(String[] args) {
        List events = new ArrayList<Filter>();
        events.add(new Filter("1", "3"));
        events.add(new Filter("1", "5"));
        events.add(new Filter("3", "13"));
        events.add(new Filter("5", "4"));
        events.add(new Filter("1", "7"));
        events.add(new Filter("8", "9"));
        events.add(new Filter("9", "1"));
        events.add(new Filter("1", "23"));
        events.add(new Filter("5", "7"));

        filterMessages(events, "1:3,3:13,5:-");
    }
}

Что код, который у меня есть, иэто работает, но я думаю, что этот подход немного сложен и также не позволяет мне адаптировать его к существующему коду, который у меня есть в настоящее время. Любая идея? или лучший подход к этому? Спасибо

1 Ответ

0 голосов
/ 06 октября 2019

Я бы посоветовал вам задать этот вопрос на сайте Code Review: https://codereview.stackexchange.com/.

Кратко:

1) Конструктор Filter(String valueFilter1, String valueFilter2) не нужен.

2) Несмотря на то, что код работает, такое определение equals() может привести к ошибкам в других случаях:

Filter a = new Filter("1", "2");
Filter b = new Filter("-", "2");
Filter c = new Filter("5", "2");
System.out.println(a.equals(b)); // true
System.out.println(b.equals(c)); // true
System.out.println(a.equals(c)); // false

Согласно здравому смыслу, если a = b и если b = c, то оно должнобыть = с. Но в вашем случае это не так. В реальном приложении это может привести к ошибкам, которые трудно найти.

...