When you have singular events which should generate an achievement as soon as they occur, like "player killed themselves with the EN cannon", then you might want to have a method for each Achievement which receives an event and then returns whether that event fulfills the condition for that achievement or not. Example:
AchievementEMCannonSelfKill extends Achievement { // ... @Override public bool check(AchievementEvent event) { if (!event instanceof KillEvent) return false;{ KillEvent killEvent = (KillEvent)event; return (killEvent.victim == player && killEvent.weapon = EN_CANNON ); else { return false; } } } Your class which processes all achievement events would have a list of not yet awarded Achievements and call the .check method on each of them to check if the event it just received fulfills that achievement.
Now what about those achievements which don't just check one event but events over a period of time, like the "Killed boss using only the nailgun".?
When you store all events over a period of time in a Collection (like an ArrayList), you can easily filter it to get only the events you need. A good way to check if something did or did not happen within a given time frame is the Java Stream API. For example, the method stream.anyMatch and stream.noneMatch can be used to find if there is any event in your event collection which can be cast to a WeaponDamageEvent where the conditions victim == finalBoss && inflictor == player && weapon != NAIL_GUN.
You could also implement achievements like this as a kind of state machine. The AchievementBossKilledOnlyWithNailGun could be switched to the "on" state when it checks the event which says that the boss game object is created, get switched to "off" when it receives an event which says that the player damaged the boss with the wrong weapon, and returns true if it receives the boss kill event while in the "on" state.