Say I need a data structure in Java involving one set of categories, each with one set of subcategories. For example, let's say the main category is 'brand' (like, of a product) and the subcategory is 'product'. I want to be able to map the combination of brand+product to a piece of data e.g. a price.
I'd like to use an enum type for both 'brand' and 'product' if they were on their own, because
Brand+product has only a small, single piece of data tied to it (the price)
I need to refer to them many times throughout a reasonably large program, so the chance that I'll mistype any string literal keys I assign to them is basically one.
However, the number of brands/products is too large to have a single enum for each brand/product combination (around twenty brands each with ten products and a good chance of adding more later). I'd like to be able to use the structure like this:
getPrice(APPLE.IPOD)
getPrice(APPLE.MACBOOK)
getPrice(HERSHEYS.PEANUT_BUTTER_CUPS)
Should I use some sort of nested enum? If so, how would that be implemented?
Bonus information: I've spent a bit of time googling 'java nested enum' but haven't come up with anything. The problem with structures like the first one in the ticked answer here or thelosts's answer here is that I have too many categories all exhibiting the same behavior to write out very similar enum definitions so many times.
I wouldn't use an enum for this.
I would suggest you load this information from a file or database. Java is not a good place for storing large amounts of data.
You could add a getter and setter to the Brand enum that allows setting a Product enum, but that will not enforce that a Product is actually manufactured by that Brand. Besides, there is ever only one instance of each enum value -- so you could never have APPLE.IPOD and APPLE.IPAD. You either need a single enum type that represents the Cartesian product, or you need to load your values from a data store like Peter Lawrey suggests.
Related
I have abstract super class and some sub classes. My question is how is the best way to keep objects of those classes so I can easily find them using all the different parameters.
For example if I want to look up with resourceCode (every object is with unique resource code) I can use HashMap with key value resourceCode. But what happens if I want to look up with genre - there are many games with the same genre so I will get all those games. My first idea was with ArrayList of those objects, but isn’t it too slow if we have 1 000 000 games (about 1 000 000 operations).
My other idea is to have a HashTable with key value the product code. Complexity of the search is constant. After that I create that many HashSets as I have fields in the classes and for each field I get the productCode/product Codes of the objects, that are in the HashSet under that certain filed (for example game promoter). With those unique codes I can get everything I want from the HashTable. Is this a good idea? It seems there will be needed a lot of space for the date to be stored, but it will be fast.
So my question is what Data Structure should I use so I can implement fast finding of custom object, searching by its attributes (fields)
Please see the attachment: Classes Example
Thank you in advanced.
Stefan Stefanov
You can use Sorted or Ordered data structures to optimize search complexity.
You can introduce your own search index for custom data.
But it is better to use database or search engine.
Have a look at Elasticsearch, Apache Solr, PostgreSQL
It sounds like most of your fields can be mapped to a string (name, genre, promoter, description, year of release, ...). You could put all these strings in a single large index that maps each keyword to all objects that contain the word in any of their fields. Then if you search for certain keywords it will return a list of all entries that contain that word. For example searching for 'mine' should return 'minecraft' (because of title), as well as all mine craft clones (having 'minecraft-like' as genre) and all games that use the word 'mine' in the 'info text' field.
You can code this yourself, but I suppose some fulltext indexer, such as Lucene may be useful. I haven't used Lucene myself, but I suppose it would also allow you to search for multiple keyword at once, even if they occur in different fields.
This is not a very appealing answer.
Start with a database. Maybe an embedded database (like h2database).
Easy set of fixed develop/test data; can be easily changed. (The database dump.)
. Too many indices (hash maps) harm
Developing and optimizing queries is easier (declarative) than with data structures
Database tables are less coupled than data structures with help structures (maps)
The resulting system is far less complex and better scalable
After development has stabilized the set of queries, you can think of doing away of the DB part. Use at least a two tier separation of database and the classes.
Then you might find a stable and best fitting data model.
Should you still intend to do it all with pure objects, then work them out in detail as design documentation before you start programming. Example stories, and how one solves them.
I am trying to design my first trading system and I am struggling with designing a correct Order object with all the FIX concepts involved in it. Wondering if any experienced folks can chime in on some ideas.
I created a simple Order class.
But as a NewOrderSingle (FIX) is generated, I need a ClOrdId.
Then when I cancel this order, I need a new ClOrdId (For every cancel and replace FIX message generated) and set the correct OrigClOrdId. So I need to keep track of those OrigClOrdIds.
Also, I think I need to keep a unique Id internal to my system to identify this order, different from ClOrdId, which could keep changing.
I don't see any nice object oriented way of designing this order object while keeping the concept of various Ids relevant to my FIX messages separate.
How do people design these in real world? Any suggestions? Thanks.
I have been involved with the design of several systems that do exactly what you are describing. It is actually more complicated than designing a class hierarchy. Some things to keep in mind:
Based on the trading venue and/or asset class, the "unique ID" of the order may actually be a combination of tags. For example, when trading on NYSE "Classic" the unique ID is actually a compound ID consisting of tag 115 (OnBehalfOfCompID) + Tag 11. For other venues, it could be Tag 109 + Tag 11, or Tag 76 + Tag 11.
In addition, you may need to add more data to your unique ID to account for the fact that IDs sent to distinct venues could be the same. For example, some venues require an Integer as their ClOrdID value. In such cases, your internal representation of the "unique ID" should be some kind of salt + the ID data, i.e. DARKCROSS-1 where the (fictional) venue is "DARKCROSS" and 1 is the tag 11 value.
If several venues have a similar strategy for resolving the unique ID of the order, you could extract that logic into a ID factories - composition over inheritance.
So, your abstraction could start with a AbstractOrder, but you may find that you need to have NyseOrder, NasdaqOrder, and so on.
(Note that some implementations I've seen have a GenericFixOrder class or some such. In practice, there is no such thing - each venue has its own specific behavior that is slightly different from others.)
Another topic is Good Til Cancel and Good Til Date orders, which generally must have IDs that are unique for all time (i.e. the ID must contain a date), and which survive your application for multiple restarts. So, your ID factory must take such orders into account.
Regarding relationship of the IDs, it is actually quite straight-forward. You have a Map of unique order IDs to Order objects. The class representing a Cancel/Replace or Cancel references the parent order (via a "Parent Order ID" field, resolved the same as the "Unique ID" field as described above).
There does not have to be a direct reference to the original ("root") New Order, in fact when the Cancel/Replace is accepted you may find it beneficial to remove it from the Map holding your orders. When the Cancel is accepted, you almost definitely can remove both it and the Order from the Map - the order is complete.
Note that the above is a general sketch - removing orders from memory, etc. could be considered a premature optimization. If your trading volumes are small, you could possibly hold all of your trading messages in memory for the entire day.
How about this class diagram?
Cancel method constructs new SubOrder that can be used to send cancel request. You could add more constructor methods for other sub order types. If cancellation order is very specific you could crate one class per order type, if they have something in common they could extend common class, AbstractOrder for example. Something like that:
I'm trying to come up with a simple way of organizing some objects, in terms of what classes to create. Let's say I'm trying to keep track of books. A book can fall under a number of different genres and subgenres. I want to be able to recognize a book as one book and yet have it fall under these different categories. I have a genre class which keeps track of all the subgenres, and a subgenre class which has all of the books in it. I want the book to know all of the genre and subgenres that it falls under. I also want to keep track of some statistics (reviews, comments, number of times read, etc.) based on genre and subgenre and then be able to aggregate them to get numbers for the entire book. In this way, a user could select a book and know, each genre/subgenre that the book belongs to, and soem statistics about that book for each category
What are some ideas for how I can design this?
My thought was to have each Book define a class called BookGroup, and the BookGroup would contain the Genre and Subgenre, along with any relevant information for that category (assuming that subgenres can only belong to one genre). Then in the Book class I would keep a set of bookgroups that the book belongs in. I can add up stats from all the different bookgroups. The only thing I don't like about this is that I feel like a BookGroup should contain Books, not the other way around.
Any other ideas?
Thanks!
Edit:
All you guys gave really good tips. I think for simplicity reasons, I might do something like this for now:
class Book
{
Genre myGenre;
SubGenre mySubGenre;
String myTitle;
}
class Library
{
Map<String,Set<Book>> allBooks = new HashMap<String,Set<Book>>();
//where allBooks contains a mapping from book title, to all of the book objects which actually represent the same book but may contain different information related to their specific genre/subgenre
}
I'd imagine you would want your classes to look something like this:
public class Book
{
String name;
List<Review> reviews;
Set<Genre> genres;
public Book(String name, Set<Genre> genres){}
}
public class Genre
{
String name;
Set<Book> books;
public Genre(String name, Set<Book> books){}
}
I am making an assumption here that you will be utilizing a database, in turn you would have a DAO to query on all known books that match a criteria and subsequently perform CRUD operations across the datasets. I feel a bit off by suggesting that the Genre constructor takes a Set of Book objects, but at the moment I can't think of another way to do this right now.
So, the problem is to do with inverse relationships, really. It's quite difficult to avoid this and maintain efficiency. A relational database sidesteps this issue by optimising in the background, using efficient query operations, and never storing the inverse relationship in the first place.
If you use a relational database in the background, you can create methods that get the book groups using a relational query without ever storing the information in Java.
I would just make two enums, one BookGenre = {scifi, novel, ...} and similar for subgenres. When creating a new Book object, add a reference to the Book object to some list which keeps track of all scifi book, etc ( i.e. make an EnumMap> which maps each genre to a list of books ); in this way you can easily access all the books of a genre.
There have been good suggestions from the other posters, but your original idea might work as well. The biggest problem for you, if I understand you correctly, appears to be one of naming: your 'BookGroup' is not really a grouping as such, but a descriptor of which group (genre/subgenre) it belongs to plus associated statistics. If you renamed it to e.g. 'BookGenreStatistics', the question of who contains what would go away.
I think you want collections pointing to each other. And when adding a book to a changre you would also add the changre to the book. Then just iterate as needed to obtain what you wanted. A changre and a sub changre should really be the same class, no need to have different classes here.
An alternative to this would be not to have references in a book to what changres it belongs to, instead if you need to know you would have to iterate through all changres and see if the book is in them. Depends on how many changres there are and how usual it is for a book to belong to a changre. Let's say if most changres have over half of all the books in them. The obvious third option is not to have books in changres, in that case you would have to iterate through the books to obtain the changres, the question is if most books belong to almost all changres, or if changres are unusual and only contain few books.
If you chose option number one, then a changre would be able to contain books and other changres, and a book would be able to contain changres but not other books. Sounds similar doesn't it? Well, it is, a changre and a book is the same thing, well, almost. The main difference is how you use them. Imagine a tree where the changres on top point down to subchangres and so forth, then they in turn point down to books who in turn point back up to the subchangres they're part of. Then in order to find all books in a changre for instance you would just have to traverse the tree from root up, except when you're at a book you stop. If a book can belong to several changres (yes, it can, right?), then you just need a loop variable in the book that's set when iterating and if the book is reached a second time you know because the variable has already been set.
For instance finding all the books in a changre:
1. Construct collection object that is to hold the result.
2. (in subclass changre) Iterate through all changres and books (they might be stored in the same collection object)
2. (same method as above, but in subclass book) Check if iteration field is set, if so just return, else add this to the result collection object.
3. Unset iteration field in all books of the result collection object to make it possible to redo from step one. (the alternative to having such an iteration field is of course use a collection that doesn't matter if you put in duplicates)
-Done, a book simply instead of iterating through the changres it has (like a changre does) knows that it has to add itself to the result.
Now that I think about it I think there's a tool that automatically generates code where you can specify things like a changre can have books and so on, and then to find all book reviews in a changre you can specify to traverse from the changre, pass at most one book on your path through the graph, and end in a review, and then agregate the results, and it generates code that does that. I don't remember the name or what language it was, but I think code like this can be generated from only a few lines, but of course writing it yourself shouldn't hurt either.
Following problem: I want to render a news stream of short messages based on localized texts. In various places of these messages I have to insert parameters to "customize" them. I guess you know what I mean ;)
My question probably falls into the "Which is the best style to do it?" category: How would you store these parameters (they may be Strings and Numbers that need to be formatted according to Locale) in the database? I'm using Hibernate to do the ORM and I can think of the following solutions:
build a combined String and save it as such (ugly and hard to maintain I think)
do some kind of fancy normalization and and make every parameter a single row on the database (clean I guess, but a performance nightmare)
Put the params into an Array, Map or other Java data structure and save it in binary format (probably causes a lot of overhead size-wise)
I tend towards option #3 but I'm afraid that it might be to costly in terms of size in the database. What do you think?
If you can afford the performance hit of using the normalized approach of having a separate table I would go with this approach. We use the same approach as your first suggestion at work, and it gets messy, especially when you reach the column limit and key/values start getting truncated!
Do the normalization.
I would suggest something like:
Table Message
id
Table Params
message_id
key
value
Storing serialized Java objects in the database is quite a bad thing in most cases. As they are hard to maintain and you cannot access them with 'simple' SQL tools.
The performance impact is not as big, as you can fetch all together in a single select using a join.
It depends a bit. Is the number of parameters huge for each entity? If it is not probable second option is the best.
If you don't want to add extra queries caused by the lazy load you can always change fetch type for the variable number of parameters that would only add one join to a query you were always doing. In normal conditions it is not a big price to pay.
Also the third and the first one forbids forever any type of queries over the parameters. A huge technical debt for the future I would not be willing to pay.
directly put it as string and save it ..
I have an application that needs to support a multilingual interface, five languages to be exact. For the main part of the interface the standard ResourceBundle approach can be used to handle this.
However, the database contains numerous tables whose elements contain human readable names, descriptions, abstracts etc. It needs to be possible to enter each of these in all five languages.
While I suppose I could simply have fields on each table like
NameLang1
NameLang2
...
I feel that that leads to a significant amount of largely identical code when writing the beans the represent each table.
From a purely object oriented point of view the solution is however simple. Each class simply has a Text object that contains the relevant text in each of the languages. This is further helpful in that only one of the language is mandated, the others have fallback rules (e.g. if language 4 is missing return language 2 which fall back to language 1 which is mandatory).
Unfortunately, mapping this back to a relational database, means that I wind up with a single table that some 10-12 other tables FK to (some tables have more than one FK to it in fact).
This approach seems to work and I've been able to map the data to POJOs with Hibernate. About the only thing you cant do is map from a Text object to its parent (since you have no way of knowing which table you should link to), but then there is hardly any need to do that.
So, overall this seems to work but it just feels wrong to have multiple tables reference one table like this. Anyone got a better idea?
If it matters I'm using MySQL...
I had to do that once... multilingual text for some tables... I don't know if I found the best solution but what I did was have the table with the language-agnostic info and then a child table with all the multilingual fields. At least one record was required in the child table, for the default language; more languages could be added later.
On Hibernate you can map the info from the child tables as a Map, and get the info for the language you want, implementing the fallback on your POJO like you said. You can have different getters for the multilingual fields, that internally call the fallback method to get the appropiate child object for the needed language and then just return the required field.
This approach uses more table (one extra table for every table that needs multilingual info) but the performance is much better, as well as the maintenance I think...
The standard translation approach as used, for example, in gettext is to use a single string to describe the concept and make a call to a translate method which translates to the destination language.
This way you only need to store in the database a single string (the canonical representation) and then make a call in your application to the translate method to get the translated string. No FKs and total flexibility at the cost of a little of runtime performance (and maybe a bit more of maintenance trouble, but with some thought there's no need to make maintenance a problem in this scenario).
The approach I've seen in an application with a similar problem is that we use a "text id" column to store a reference, and we have a single table with all the translations. This provides some flexibility also in reusing the same keys to reduce the amount of required translations, which is an expensive part of the project.
It also provides a good separation between the data, and the translations which in my opinion is more of an UI thing.
If it is the case that the strings you require are not that many after all, then you can just load them all in memory once and use some method to provide translations by checking a data structure in memory.
With this approach, your beans won't have getters for each language, but you would use some other translator object:
MyTranslator.translate(myBean.getNameTextId());
Depending on your requirements, it may be best to have a separate label table for each table which needs to be multilingual. e.g.: you have a XYZ table with a xyz_id column, and a XYZ_Label table with a xyz_id, language_code, label, other_label, etc
The advantage of this, over having a single huge labels table, is that you can do unique constraints on the XYZ_labels table (e.g.: The english name for XYZ must be unique), and you can do indexed lookups much more efficiently, since the index will only be covering a single table at a time (e.g.: if you need to look up XYZ entities by english name) .
What about this:
http://rob.purplerockscissors.com/2009/07/24/internationalizing-websites/
...that is what user "Chochos" says in response #2