I would compare this to a map API: an access could throw if a key wasn't present, but you can check to see if the key was in there first anyways. As long as the map isn't being used concurrently, it isn't that much of a problem, and if it is being used concurrently, then you need a different design. In the former case, separating "exists" and "get" would be considered over-engineering.
I guess databases and file systems are different because concurrent access is the norm, not the exception, and APIs should be designed accordingly. But for most of your in-memory structures, you probably don't want them dealing with concurrency because they aren't going to be able do that very well anyways (instead, deal with concurrency outside of the data structure and have them throw when inconsistencies from bad concurrency policies arise).