How to give each object in a document a unique ID? - java

I'm making a bitmap editor where a document consists of several layers where each layer represents a bitmap. Each layer must have a unique ID compared to all other layers that currently exist in the document. I also need to take into account that I need to save and load documents along with the layer IDs.
I'm using the command pattern to store actions that are performed on the document and the unique IDs are used to keep track of which layer an action should be performed on.
At the moment, I just keep a counter called X, when a new layer is created its ID is set to X then X is incremented. When loading, I need to make sure X is set to an appropriate number so that new layers are given unique IDs i.e. I could save the value of X and restore that, or set X based on the biggest layer ID loaded.
Given X is a 32-bit number, the user will need to create 4,294,967,296 layers working on the same file before IDs start to be reused which will cause weird behaviour. Should I implement a better unique ID system or is this generally good enough?
I'm in Java so I could use the UUID library which creates 128 bit unique IDs according to a standard algorithm. This seems overkill though.
Is there some general approach to this kind of problem?

This is perfectly good enough. At a rate of ten new layers per second 24/365, which is silly, it'll run fine for roughly three years.

If you think you might manipulate layers programmatically, and thus have some possibility of having 2^32 layers in the lifetime of the image, then throw all the layer IDs into a HashSet when you read the file, and update that set when you add/remove layers. (You don't need to explicitly store the set; the ID associated with each mask is enough.) Then instead of taking "the next number", take "the next number not in the set". Having a counter is still useful, but whether you set it to 0 or (max+1) when you read a file is immaterial; it won't take a significant amount of time to find an empty space unless you envision bafflingly large numbers of layers present simultaneously.
But since you're using Java, you could just use a long instead of an int, and then you wouldn't ever (practically speaking) be able to overflow the number even if all you did was create a one-pixel mask and destroy it over and over again.

Related

Speed a search cache without using too much memory

I have to access a database with 380,000 entries. I don't have write access to the DB, I can just read it. I've made a search function using a map to search for users by firstname. Here is my process:
1 - Load everything from the DB
2 - Store everything into a Map<Charactere, ArrayList<User>>, using Alpha letters to store users according to the first letter of their firstname.
<A> {Alba, jessica, Alliah jane, etc ...}
<B> {Birsmben bani, etc ...}
When someone searches for a user, I take the firstletter of the firstname typed and use map.get(firstletter), then iterate on the ArrayList to find all the users.
The Map Take a huge space in the memory I guess (380,000 User object). I had to increase the heap size
I want to make it faster. Use firstname as key for the Map, in order to make it faster (there are many people with the same firstname).
I have two solutions in mind:
1 - Still use a map with firstname as key (increasing the heap size again?)
2 - Use files on the disk instead of Map (Alba.dat will contain all Alba for example) and open the right file for each search. No need to incease the heap size, but are there any side effects?
Which one is better? (pros and cons)
Update with more info
It's a database of customers who calls our customer service on the phone. The person who takes the call has to search using the customers names (usually firstname and then lastname). Using the Db is too slow to search. The solution I've implemented is much faster already (1/2 seconds vs 26 seconds using the db), but I want to improve it.
IMHO, I don't think you have to cache all the entries in memory, but a part of them, maybe:
Maybe just use a ring buffer, or
More complicated, and make more sense, to implement a LFU Cache, that keeps the N top most frequently accessed item only. See this question for a hint of how to implement such a cache.
There are several issues with your approach:
It implies that the number in users doesn't change, a good application design would work with any number of users without software change
It implies that the current problem is the only one. What happens if the next requirement that needs implementation is "search by caller id" or "search by zip code"?
It is reinventing the wheel, you are currently starting to write a database, index or information retrieval solution (however you want to name it) from scratch
The right thing to do is to export the user data into a database engine which provides proper search capabilities. The export/extraction hopefully can be speed up, if you have modification time stamps or if you can intercept updates and reapply it to your search index.
What you use for your search does not matter to much, a simple database on a modern system is fast enough. Most also provide indexing capabilities to speed up your search. If you want something which can be embedded in your application and is specialized on search and solves your problems above, I'd recommend using Lucene.

How can I implement a dynamic selection?

I am making a strategy game AI. Specifically, I'm using BWMirror java library to make Starcraft: BroodWar zerg AI.
I came accross a problem with unit management. Player has some units in his disposition, let's say it's List<Unit> with such contents:
Offset Name Position
0. Drone [Worker]
1. Drone [Worker]
2. Zergling [Fighter]
3. Hatchery [Building]
4. Drone [Worker]
5. Larva [Passive]
Some functions obviously only work with unit subsets. I have implemented a method that selects subset from the main list and returns it as new list. For workers, I'd get:
Offset Name Position
0. Drone [Worker]
1. Drone [Worker]
2. Drone [Worker]
Now if one of these workers is removed from the original list (eg. because it dies), it will persist in this sub-list. There are 2 possible solutions and I don't like either:
Generate the selection list every time when needed.
Assign some event callbacks to remove items in all lists they are present in.
My questions is: Is there any kind of data storage that would let me make sub-selections but allow me to keep the data synchronized?
This means I'd have two Iterable objects and one would contain all units, other would contain workers. And removing worker from all units would also make it disappear from workers, without any callback.
I think you only have the 2 options you listed, and of the two, I think your first option makes the most sense.
Lazily generating the list only when you needed it would save a lot of cycles. One stim packed up Marine (such as yourself) , might kill a huge number of zerglings, you really don't want to be sending messages for every zergling that dies. It would be much better to just see what you have left when you need them.

Serializing java.util.Random

I'm working on a small, simple game (mostly to learn what's new in Java 8 and JavaFX). One of the features I have is the ability to seed the game's random number generator so you can play roughly the same game as a friend on a different system (think Minecraft Maps or The Binding of Isaac games).
I would like to add the ability to save the game to be resumed at a later time. After looking over the documentation for the java.util.Random class, I can't find a way to get the current seed of the random number generator. The only ways I have come up with to restore the random number generator after saving the game is to either access the seed via reflection at save time and use that, or to seed the initial seed at load time and just call nextInt() over and over again until we've rolled forward the random number generator enough to be where it was before the game was saved.
First of all, as #user2357112 points out, Random implements Serializable, and does so by writing the seed field (along with the nextNextGaussian and haveNextNextGaussian fields). Have you tried simply serializing it? That should 'just work'™. Other serializers, like Gson, also work. gson.fromJson(gson.toJson(r), Random.class); returns an identical object.
You don't necessarily need the same Random instance, just a consistent one. You could simply call nextLong() and write that value to your save file as random_seed or whatever. Then just initialize a Random instance with that seed, and now all runs loaded from that file will behave the same. If you wanted, you could even reset the Random instance in your currently running game to the same seed too.
On the other hand if you're generating maps or other seemingly-constant content randomly and want it to persist between loads, I'd think you'd do better to simply seed your Random at the start, and save that value like you describe. To save on computation you could do this in chunks smaller than a whole level. For example, split each level into 10ths, and use (and save) a different seed for each 10th. Then you just have to generate the portion the user's on now, and not the parts they've already crossed. If you were to only save the current state like you propose, the user couldn't go backwards in the map (which might not be a problem for your game in particular, but wouldn't be a great practice in general).
UX caveat: saving your game's randomness seems potentially over-engineered. As a user, I don't generally expect a save file to persist randomness. In fact, sometimes players take advantage of that, for instance if they die in a random encounter right after saving, reloading the game doesn't immediately drop them back into the same encounter. I would consider just leaving your game's Random unseeded and let each game be slightly unique.

RandomaAccessFile, what is actually random?

Having read this oracle java link I would like to know what the writers of this class exactly meant by the term "Random", if the buffer has its own position, limit, capacity indicators. What would be randomly done? I think I am just misinterpreting the word Random in that context.
Is anybody able to clarify the point in other terms?
Thanks in advance.
Random access refers to the ability to access data at random. The opposite of random access is sequential access. To go from point A to point Z in a sequential-access system
For example in Random access file you can access any random position where you want, but for sequential access file you have to go from beginning to that specific point to get the data
according to wikipedia
random access (sometimes called direct access) is the ability to
access an element at an arbitrary position in a sequence in equal
time, independent of sequence size. The position is arbitrary in the
sense that it is unpredictable, thus the use of the term "random" in
"random access"
you can also see this link (or thousands of other search results) to get a clear idea about "random access"

Need help storing/retrieveing data

A user has an ArrayList of numbers. Those numbers correspond to the applications that they have access to. Certain applications have different entitlement numbers(ie- 3, 72, etc.). What I want to do is store this data in a map so that when the user logs in, they can input their numbers into the Map and quickly get the applications that they are entitled to. However, some applications require 2 to 3 entitlement numbers. For example, one entry could be: ("101 and 234", "Application 1"). I was wondering if there was an ideal way of retrieving all of the values from the map that that users entitlement numbers satisfies.
How I currently have it, the program compares the users data to each application and confirms or denies access. This seems inefficient. Any help us greatly appreciated!
Note: I am reading the applications and their numbers in from an XML, so I can store them as I wish.
If there are large numbers of numbers required per application, the best approach is to use set intersection. If the numbers are contiguous or at least dense, you can optimize this into a bitset. For only one or two numbers though, I'd recommend just testing each number individually, since it's likely to be faster than full set operations.
The solution:
Define a class for each application (let's call it App). The class contains the name of the application, and a (sorted) List/array of entitlements.
Use Map to map from String to App: Map<String, App> for all single entitlement apps (you can use HashMap or TreeMap - your choice). If there are multiple apps that only need one and the same entitlement, consider Map<String, List<App>>. Exclude the apps that need multiple entitlements from the Map, and store them in a separate List/array instead.
When you are given a list of entitlements to retrieve apps, loop through the list and just grab everything that the Map maps the String to. For those that needs multiple entitlements, just check individually (you can speed up the checking a bit by sorting the list of entitlements given, and storing the entitlements to each App in sorted order - but it may not even matter since the size is small).
The solution reduces the time complexity for the operation. However, a few hundred apps times the number of entitlements of around 10 is quite small in my opinion, unless you call this many times. And it's better to time your original approach and this approach to compare - since the overhead might shadows any improvement in time.
A bit of further improvement (or not) is:
Use Map<String, List<App>> and include even apps that need multiple entitlements (those app will be mapped to by many entitlements).
When we search for app, we will use a Map<App, Integer> to keep track of how many entitlements that we have confirmed for multiple entitlement apps. So the flow will be like:
new mapAppInteger
foreach entitlement in inputListOfEntitlement
listOfApps = mapStringAppList.get(entitlement)
if listOfApps found
for each app in listOfApps
if app needs singleEntitlement
put app in output list
else // needs multiple
if app is in mapAppInteger
map app --> count + 1
if mapAppInteger.get(app) == app.numberOfRequiredEntitlement
put app in output list
remove app from mapAppInteger
else // not in mapAppInteger
map app --> 1

Categories

Resources