[SOLVED] Iterate and clear hashmap?

Dear all,

I use a hashmap to control a couple of timers:

var Map<String, Timer> timers = newHashMap

The background is that I record LastUpdated timestamps of Homematic sensors to fire an alarm after a predefined amount of time (e.g. “sensor not updated since …”) like this:

timers.put(triggeringItem.name, createTimer(now.plusHours(MAX_HOURS_BETWEEN_UPDATES) , [ |
	// Timer fires after MAX_HOURS_BETWEEN_UPDATES
	// ... additional code ...
	timers.get(triggeringItem.name).reschedule(now.plusHours(6)) // repeat warning after 6 hours
]))

From time to time I want to clear / reset the whole hashmap which means to set it to an empty hashmap again:

timers = newHashMap

But this is obviously not sufficient because the existing timers are still running and will fire over and over again as they are rescheduled. What I need now is an algorithm to iterate through my existing hashmap to get a hold onto my timers and cancel all of them before I finally reset the hashmap. I have searched the forum but have not found anything useful for my issue.Who can help me with that?

Yes. What you store in your map is a handle, a pointer, to an independent timer. Destroying the handle does not affect the timer itself.

Your entries are keyed by Item name, no? I’d look at iterating through a group of your Items.

1 Like

Yes, that is what I learned. :wink:

You are right. The item names within the hashmap are not really known but the members of the triggering group definitely are! So now I am looping through its members and test whether they have an associated timer running. That’s it! Thank you, @rossko57!

This is my working solution:

	gHMLastUpdate.members.forEach[sensor |
		var Timer timer = timers.get(sensor.name)
		if (timer !== null) {
			logInfo(LOG_NAME, "sensor.name=" + sensor.name + " | " + timer.isRunning()  )
			timer.cancel()
			timer = null
		}
	]
	timers = newHashMap

(Never mind, I still wonder if there is a way to iterate through a hashmap but I consider this issue solved. :wink:)

I honestly don’t know @rlkoshak has sworn off DSL rules :slight_smile: but may recall.
It’s probably as simple as myHashmap.forEach(blah)

Not sworn off, but knowledge of programming languages slowly degrades without continuous use.

But I know the answer to that, but the question is what do you want to iterate over, the keys or the values?

myHashmap.keys.forEach[ key | blah blah blah ]

myHashmap.values.forEach[ value | blah blah blah ]
    myHashmap.values.forEach[ value | value.cancel ]
    myHashmap.clear
2 Likes

Thank you, Rich. That works! I tried something “similar” before but it failed somehow. I must have done something wrong… The solution is even shorter now:

timers.values.forEach[timer |
	if (timer !== null) {
		logInfo(LOG_NAME, "timer=" + timer + " | " + timer.isRunning())
		timer.cancel()
	}
]
timers.clear

Thank you both @rossko57 & @rlkoshak for your help!

It will be impossible for timer to be null so you don’t need that if statement. To remove a key/value pair from a Hashmap you set the value to null so it is impossible to have null values.

1 Like