Java 8 - лямбда-выражения и потоки для перебора HashMap из HashMap - PullRequest
0 голосов
/ 04 декабря 2018

Мне нужно перебрать HashMap из HashMap с помощью лямбда-выражений и отфильтровать несколько нежелательных записей.Я попробовал несколько подходов, но это не похоже на работу.Ниже приведена структура карты.

Map<String, Map<Date, String>> sensor_tags = new HashMap<String, Map<Date,String>>();

Из этой карты мне нужно удалить записи, в которых данные датчика старше определенной даты (дата является ключом внутренней карты).Ниже приведены примеры данных для карты sensor_tags-

String tagName = "zoneSensor";
Map<Date, String> values= new HashMap<Date, String>();

// (1st entry for tag 1) --> date is day before yesterday
Calendar datekey1 = Calendar.getInstance();
datekey1.set(2018, 12, 01, 12, 30, 45);
values.put(datekey1.getTime(), "ON");

// (2nd entry for tag 1) --> date is yesterdys date
Calendar datekey = Calendar.getInstance();
datekey.set(2018, 12, 02, 12, 30, 45);
values.put(datekey.getTime(), "OFF");

// (3rd entry for tag 1) --> date is today
Calendar instance = Calendar.getInstance();
instance.set(2018, 12, 03, 12, 30, 45);
values.put(instance.getTime(), "ON");

//(4th entry for tag 1)--> date is today + 10 sec
instance.add(Calendar.MILLISECOND, 10000);
sensor_tags.put(tagName, values);

values.put(instance.getTime(), "ON");
sensor_tags.put(tagName, values);

// 5th entry for tag2
tagName = "zoneSensor1";
values= new HashMap<Date, String>();
values.put(Calendar.getInstance().getTime(), "NORMAL");
sensor_tags.put(tagName, values);

//code in java 7
for (final Entry<String, Map<Date, String>> entry : sensor_tags.entrySet()) {
            final Iterator<Date> iter = entry.getValue().keySet().iterator();
            while (iter.hasNext()) {
                final Date date = iter.next();
                if (date.before(givendate)) {
                    iter.remove();
                }
        }
}

// code tried in java 8 (I am a beginner here :-) )
 sensor_tags
            .entrySet()
            .stream()
            .map(Map.Entry::getValue) // get an inner map
            .filter(value -> ((Date)value).before(datekey.getTime()));

Как я могу выполнить итерацию и отфильтровать данные для внутренних карт?Кроме того, после того как данные отфильтрованы, мне нужно сохранить структуру карты как есть, следовательно, выходные данные нужно собирать только в Map<String, Map<Date, String>>.

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

, если вы не хотите изменять существующую карту, тогда нет необходимости в потоке, вы можете упростить свой императивный подход до:

for (final Map<Date, String> v : sensor_tags.values()) {
      v.keySet().removeIf(d -> d.before(datekey.getTime()));
}

, если вы не хотите изменять существующую картутогда вы можете сделать:

Map<String, Map<Date, String>> result = sensor_tags.entrySet()
     .stream()
     .collect(toMap(
         Map.Entry::getKey, 
         e -> e.getValue().entrySet().stream()
                                     .filter(a -> !a.getKey().before(datekey.getTime()))
                                     .collect(toMap(Map.Entry::getKey, 
                                                    Map.Entry::getValue))));
0 голосов
/ 04 декабря 2018

Я сделал эти два метода для вас.Первый создает новый hashmap, а второй меняет ваш Hashmap на лету с желаемой фильтрацией.Я не проверял угловые случаи, но они, кажется, работают.Надеюсь, это поможет:

Сохраняет вашу хэш-карту

private Map<String, Map<Date, String>> getFilteredResultsKeeping(Map<String, Map<Date, String>> sensor_tags,
        Date givendate) {
    return sensor_tags.entrySet().stream()
            .map(sensorValue -> new SimpleEntry<>(sensorValue.getKey(),
                    sensorValue.getValue().entrySet().stream()
                            .filter(sensor -> !sensor.getKey().before(givendate))
                            .map(sensor -> sensor.getKey())
                            .collect(toMap(date -> date, date -> sensorValue.getValue().get(date)))))
            .collect((toMap(SimpleEntry::getKey, SimpleEntry::getValue)));
}

Изменяет вашу хэш-карту

private Map<String, Map<Date, String>> getFilteredResultsRemoving(Map<String, Map<Date, String>> sensor_tags,
        Date givendate) {
    return sensor_tags.entrySet().stream()
            .peek(sensorValue -> {
                List<Date> invalidDates = sensorValue.getValue().entrySet().stream()
                        .map(sensor -> sensor.getKey())
                        .filter(date -> date.before(givendate)).collect(Collectors.toList());
                invalidDates.forEach(date -> sensorValue.getValue().remove(date));
            })
            .collect((toMap(Entry::getKey, Entry::getValue)));
}
0 голосов
/ 04 декабря 2018

Если вы хотите изменить существующую карту, вам не нужны потоки.Просто сделайте цикл и позвоните removeIf():

sensor_tags.values().forEach(
        m -> m.keySet().removeIf(datekey.getTime()::after));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...