Properties in java - can we have comma-separated keys with single value? - java

I want to have multiple keys (>1) for a single value in a properties file in my java application. One simple way of doing the define each key in separate line in property file and the same value to all these keys. This approach increases the maintainability of property file. The other way (which I think could be smart way) is define comma separated keys with the value in single line. e.g.
key1,key2,key3=value
Java.util.properties doesn't support this out of box. Does anybody did simillar thing before? I did google but didn't find anything.
--manish

I'm not aware of an existing solution, but it should be quite straightforward to implement:
String key = "key1,key2,key3", val = "value";
Map<String, String> map = new HashMap<String, String>();
for(String k : key.split(",")) map.put(k, val);
System.out.println(map);

One of the nice things about properties files is that they are simple. No complex syntax to learn, and they are easy on the eye.
Want to know what the value of the property foo is? Quickly scan the left column until you see "foo".
Personally, I would find it confusing if I saw a properties file like that.
If that's what you really want, it should be simple to implement. A quick first stab might look like this:
Open file
For each line:
trim() whitespace
If the line is empty or starts with a #, move on
Split on "=" (with limit set to 2), leaving you with key and value
Split key on ","
For each key, trim() it and add it to the map, along with the trim()'d value
That's it.

Since java.util.Properties extends java.util.Hashtable, you could use Properties to load the data, then post-process the data.
The advantage to using java.util.Properties to load the data instead of rolling your own is that the syntax for properties is actually fairly robust, already supporting many of the useful features you might end up having to re-implement (such as splitting values across multiple lines, escapes, etc.).

Related

How to store over 300 words with definitions in a Android studio

I'm trying to create an android app where you can learn hard words its over 300 words. I'm wondering how I should store the data in java.
I have a text file where all the words are. I have split the text so I have one array with the words and another Array with the definitions, they have the same index. In an activity, I want to make it as clean as possible, because sometimes I need to delete an index and It's not efficient to that with an ArrayList since they all need to move down.
PS. I really don't wanna use a database like Firebase.
Instead of using two different arrays and trying to ensure that their order/indices are matched, you should consider defining your own class.
class Word {
String wordName;
String wordDefinition;
}
You can then make a collection of this using ArrayList or similar.
ArrayList<Word> wordList;
I know you were concerned about using an ArrayList due to the large number of words, however I think for your use case the ArrayList is fine. Using a database is probably overkill, unless if you want to put in the whole dictionary ;)
In any case, it is better to define your own class and use this as a "wildcard" to collection types which accept these. This link may give you some ideas of other feasible data types.
https://developer.android.com/reference/java/util/Collections
I personally would use a HashMap.
The reason for this is because you can set the key to be the word and the value to be the definition of the word. And then you can grab the definition of the word by doing something like
// Returns the definition of word or null if the word isn't in the hashmap
hashMapOfWords.getOrDefault(word, null);
Check out this link for more details on a HashMap
https://developer.android.com/reference/java/util/HashMap

(Java) Saving/Loading an ArrayList using Properties

I have been researching different methods for saving and loading configuration settings for my application. I've looked into Preferences, JSON, Properties and XML but I think I've settled on using the Properties method for most of my application settings.
However, I'm not able to find any information on how to best save and load an ArrayList from that file. It seems there are only individual key/pair string combinations possible.
So my question is basically, is there a better way to do this? I have an ArrayList of Strings in my application that I need to be able to save and load. Can this be done with Properties or do I need to use a separate file just to hold this list and then read it in as an ArrayList (per line, perhaps)?
EDIT: I should mention, I would like to keep all config files as readable text so I am avoiding using Serialization.
You can use commas to place multiple values on the same key.
key:value1,value2,value3
Then split them using the split function of a string after reading them in which will give you a String[] array which can be turned into an ArrayList via Arrays.asList().
Here's a partial MCVE:
ArrayList<String> al = new ArrayList<>();
al.add("value1");
al.add("value2");
al.add("value3");
String values = al.toString();
//Substring used to get rid of "[" and "]"
prop.setProperty("name",values.substring(1,values.length() - 1);
I found that using the following combination worked perfectly in my case.
Save:
String csv = String.join(",", arrayList());
props.setProperty("list", csv);
This will create a String containing each element of the ArrayList, separated with a comma.
Load:
arrayList = Arrays.asList(csv.split(","));
Takes the csv String and splits it at each comma, adding the elements to the arrayList reference.
I've seen two approaches for writing lists to a Properties file. One is to store each element of the list as a separate entry by adding the index to the name of the property—something like "mylist.1", "mylist.2". The other is to make a single value of the elements, separated by a delimiter.
The advantage of the first method is that you can handle any value without worrying about what to do if the value contains the delimiter. The advantage of the second is that you can retrieve the whole list without iterating over all entries in the Properties.
In either case, you probably want to write a wrapper (or find a library) around the Properties object that adds methods to store and retrieve lists using whichever scheme you choose. Often these wrappers have methods to validate and convert other common data types, like numbers and URLs.

Jackson JSON API: Find all occurrences of key in a string

I've used Jackson off and on for a while, so I'm familiar with it, but it has been a while and I find myself facing a little issue that I feel should be simpler than what I'm seeing, but I could be wrong.
I have a JSON string in Java. I need to find all occurrences of a particular key within that string. This key could pop up in a number of places, either in the root object, subobject, or an array of objects with who knows how much nesting. Basically, I need to find all instances of this key (along with the value), rename the key, and change the value. It's also possible that this key will not exist at all, depending on the string.
Basically, I need to find key "a", but I could have any of the following:
{b: 3, c: [{a: 0},{a: 7}]}
{a: 5, c: [], f: {a: 12}}
You get the idea. The structure has some variability to it, but in all cases I need to find all (if any) occurrences of this key and make the needed changes. Is there a simple way to do this? In a nutshell, I know that I could do something like this:
Map<String, Object> map = objectMapper.readValue(...);
And iterate through the Map, typechecking, recursing, etc as needed, but that seems to be an excessive amount of code for this. I know I could do something similar with ObjectMapper.readTree(), but then I'd be doing a pretty similar operation (typecheck, iterate, recurse), perhaps with a little less code, but still bulky. I feel like there should be a simpler way, but maybe I'm mistaken.
I am guessing that what you are looking for could be one of methods in JsonNode:
findValues()
findValuesAsText()
findParents(...)
which are all slight variations of finding values of fields with given field name; returning either List of JsonNodes (first and third), or List of Strings (second).

Need help to decide about datastructure of my project

I try to index lots of words and group them in different files. I mean for each alphabet character I consider a file, like a.txt,b.txt,...
My idea is this structure but I am looking for better strcucture because for each hashmap's key (word) has one file and no need to have other hashmap.
HashMap<String, HashMap<String,ArrayList<Posting>>>
for example
HashMap<"book", HashMap<"b.txt",ArrayList<Posting>>>
HashMap<"baby", HashMap<"b.txt",ArrayList<Posting>>>
Why do you need a nested hashmap? You can always conclude the file name from the word itself. Alternatively - wrap the word and file name in the object that will be used as a key in single level hashmap.

Get a value from hashtable by a part of its key

Say I have a Hashtable<String, Object> with such keys and values:
apple => 1
orange => 2
mossberg => 3
I can use the standard get method to get 1 by "apple", but what I want is getting the same value (or a list of values) by a part of the key, for example "ppl". Of course it may yield several results, in this case I want to be able to process each key-value pair. So basically similar to the LIKE '%ppl%' SQL statement, but I don't want to use a (in-memory) database just because I don't want to add unnecessary complexity. What would you recommend?
Update:
Storing data in a Hashtable isn't a requirement. I'm seeking for a kind of a general approach to solve this.
The obvious brute-force approach would be to iterate through the keys in the map and match them against the char sequence. That could be fine for a small map, but of course it does not scale.
This could be improved by using a second map to cache search results. Whenever you collect a list of keys matching a given char sequence, you can store these in the second map so that next time the lookup is fast. Of course, if the original map is changed often, it may get complicated to update the cache. As always with caches, it works best if the map is read much more often than changed.
Alternatively, if you know the possible char sequences in advance, you could pre-generate the lists of matching strings and pre-fill your cache map.
Update: Hashtable is not recommended anyway - it is synchronized, thus much slower than it should be. You are better off using HashMap if no concurrency is involved, or ConcurrentHashMap otherwise. Latter outperforms a Hashtable by far.
Apart from that, out of the top of my head I can't think of a better collection to this task than maps. Of course, you may experiment with different map implementations, to find the one which suits best your specific circumstances and usage patterns. In general, it would thus be
Map<String, Object> fruits;
Map<String, List<String>> matchingKeys;
Not without iterating through explicitly. Hashtable is designed to go (exact) key->value in O(1), nothing more, nothing less. If you will be doing query operations with large amounts of data, I recommend you do consider a database. You can use an embedded system like SQLite (see SQLiteJDBC) so no separate process or installation is required. You then have the option of database indexes.
I know of no standard Java collection that can do this type of operation efficiently.
Sounds like you need a trie with references to your data. A trie stores strings and lets you search for strings by prefix. I don't know the Java standard library too well and I have no idea whether it provides an implementation, but one is available here:
http://www.cs.duke.edu/~ola/courses/cps108/fall96/joggle/trie/Trie.java
Unfortunately, a trie only lets you search by prefixes. You can work around this by storing every possible suffix of each of your keys:
For 'apple', you'd store the strings
'apple'
'pple'
'ple'
'le'
'e'
Which would allow you to search for every prefix of every suffix of your keys.
Admittedly, this is the kind of "solution" that would prompt me to continue looking for other options.
first of all, use hashmap, not hashtable.
Then, you can filter the map using a predicate by using utilities in google guava
public Collection<Object> getValues(){
Map<String,Object> filtered = Maps.filterKeys(map,new Predicate<String>(){
//predicate methods
});
return filtered.values();
}
Can't be done in a single operation
You may want to try to iterate the keys and use the ones that contain your desired string.
The only solution I can see (I'm not Java expert) is to iterate over the keys and check for matching against a regular expression. If it matches, you put the matched key-value pair in the hashtable that will be returned.
If you can somehow reduce the problem to searching by prefix, you might find a NavigableMap helpful.
it will be interesting to you to look throw these question: Fuzzy string search library in Java
Also take a look on Lucene (answer number two)

Categories