Two arrays or one in Map structure? - data-structures

I'm trying to create a Map where the data will be static and not change after the program starts (actually loaded from a server)
Is it better to have two arrays, e.g. in Java:
String keys[] = new String[10];
String values[] = new String[10];
where keys[i] corresponds to values[i]?
or to keep them in a single array, e.g.
String[][] map[] = new String[10][2];
where map[i][0] is the key and map[i][1] is the value?
Personally, the first makes more sense to me, but the second makes more sense to my partner. Is either better performance-wise? Easier to understand?
Update: I'm looking to do this in JavaScript where Map and KeyValuePairs don't exist

Using a Map implementation (in Java) would make this easier to understand as the association is clearer:
static final Map<String, String> my_map;
static
{
my_map = new HashMap<String, String>();
// Populate.
}

A Hashtable looks like what you need. It hashes the keys in such a way that lookup can happen in O(1).

So, you're looking to do this in javascript. Any array or object in js in a map, so you could just do
var mymap = {'key1':'value1','key2':'value2'};

Related

Creating a stream of booleans from a boolean array? [duplicate]

There is no nice way to convert given boolean[] foo array into stream in Java-8 in one statement, or I am missing something?
(I will not ask why?, but it is really incomprehensible: why not add stream support for all primitive types?)
Hint: Arrays.stream(foo) will not work, there is no such method for boolean[] type.
Given boolean[] foo use
Stream<Boolean> stream = IntStream.range(0, foo.length)
.mapToObj(idx -> foo[idx]);
Note that every boolean value will be boxed, but it's usually not a big problem as boxing for boolean does not allocate additional memory (just uses one of predefined values - Boolean.TRUE or Boolean.FALSE).
You can use Guava's Booleans class:
Stream<Boolean> stream = Booleans.asList(foo).stream();
This is a pretty efficient way because Booleans.asList returns a wrapper for the array and does not make any copies.
of course you could create a stream directly
Stream.Builder<Boolean> builder = Stream.builder();
for (int i = 0; i < foo.length; i++)
builder.add(foo[i]);
Stream<Boolean> stream = builder.build();
…or by wrapping an AbstractList around foo
Stream<Boolean> stream = new AbstractList<Boolean>() {
public Boolean get(int index) {return (foo[index]);}
public int size() {return foo.length;}
}.stream();
Skimming through the early access JavaDoc (ie. java.base module) of the newest java-15, there is still no neat way to make the primitive boolean array work with Stream API together well. There is no new feature in the API with treating a primitive boolean array since java-8.
Note that there exist IntStream, DoubleStream and LongStream, but nothing like BooleanStream that would represent of a variation of a sequence of primitive booleans. Also the overloaded methods of Stream are Stream::mapToInt, Stream::mapToDouble and Stream::mapToLong, but not Stream::mapToBoolean returning such hypothetical BooleanStream.
Oracle seems to keep following this pattern, which could be found also in Collectors. There is also no such support for float primitives (there is for double primitives instead). In my opinion, unlike of float, the boolean support would make sense to implement.
Back to the code... if you have a boxed boolean array (ie. Boolean[] array), the things get easier:
Boolean[] array = ...
Stream<Boolean> streamOfBoxedBoolean1 = Arrays.stream(array);
Stream<Boolean> streamOfBoxedBoolean2 = Stream.of(array);
Otherwise you have to use more than one statement as said in this or this answer.
However, you asked (emphasizes mine):
way to convert given boolean[] foo array into stream in Java-8 in one statement.
... there is actually a way to achieve this through one statement using a Spliterator made from an Iterator. It is definetly not nice but :
boolean[] array = ...
Stream<Boolean> stream = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<>() {
int index = 0;
#Override public boolean hasNext() { return index < array.length; }
#Override public Boolean next() { return array[index++]; }
}, 0), false);

Trie with association between words

I have a usecase where i want to correct words.
I have set of correct and incorrect words[spelling mistake].
I populate the trie with all words.
i have both the correct and incorrect version of every word.
Now in case if i get word as "a" for correction ,
-- i search it in trie.if trie has this word , i want to associate this word with the correct version of this word.
Solution :
i can set correct version ["a1"] of word at last node of incorrect word in trie. And can resolve it to "a1" .
But i have to store correct version of each word at last node that will increase the memory foot print .
Since i have all words loaded in to trie [correct/incorrect].
Is there any way i can make association between correct and incorrect word without again storing entire word in last node as value ?
Any pointer ?
public class TrieNode<T> {
private Map<Character, TrieNode<T>> childs;
private boolean complete;
private T value;
....
}
You could use a single dictionary for this. In C#, that would be:
Dictionary<string, string> MisspellingsLookup = new Dictionary<string, int>();
The key is the misspelling, and the value is the correct spelling.
Now, some words are commonly misspelled in multiple ways. For example, "occasion" is often misspelled as "ocassion" or "occassion" If you want to reduce the memory used by the multiple misspellings, you can use a temporary dictionary during construction. Whenever you add a misspelling, you look up the correct spelling in the good words dictionary, and if it's already there then you use that value. So all you do is store a reference to an existing word rather than creating a new string. Here's an example:
Dictionary<string, string> GoodWords = new Dictionary<string, int>();
Dictionary<string, string> Misspellings = new Dictionary<string, string>();
void AddMisspelling(string misspelled, string correct)
{
string goodWord;
if (!GoodWords.TryGetValue(correct, out goodWord))
{
goodWord = correct;
GoodWords.Add(correct, correct);
}
// Always use goodWord here, so you're not creating duplicate strings.
Misspellings.Add(misspelled, goodWord);
}
When you're done adding words, you can clear the GoodWords dictionary to save space:
GoodWords = null;
I recommend a dictionary here because it'll almost certainly use less memory, and lookup is O(1) rather than O(word length).

Sorting Map/TreeMap/LinkedHashMap by Value (custom data structures)

I am currently having some issues in trying to sort a Map<String, IncreaseDetails>, where IncreaseDetails is simply a custom data structure holding a few fields.
So far I have understood fairly clearly that using a TreeMap is heavily discouraged as a TreeMap should be sorted by the KeySet rather than the actual values.
I have therefore tried to switch to both HashMap and LinkedHashMap but simply calling
Collections.sort(map,comparator) doesn't seem to do the trick. Since Java 8 I was planning on trying to use the Stream API, but I don't really know it too well.
So far my comparator looks like this:
import java.util.Comparator;
import java.util.Map;
public class CompTool implements Comparator<Float> {
Map<String, IncreaseDetails> unsortedMap;
public CompTool(Map<String, IncreaseDetails> unsortedMap)
{
this.unsortedMap = unsortedMap;
}
public int compare(Float countryOne, Float countryTwo)
{
Float countryOneValue = unsortedMap.get(countryOne).getRealIncrease();
Float countryTwoValue = unsortedMap.get(countryTwo).getRealIncrease();
return countryTwoValue.compareTo(countryOneValue);
}
}
Any suggestion would be very much welcome, as I have found a lot of similar questions or videos but none too useful for my current situation.
Your question is somewhat unclear. I assume that you want to sort the unsortedMap entries by the value stored in getRealIncrease in reversed order. This can be done by creating the stream of original map entries, sorting and collecting the result into the LinkedHashMap, which preserves insertion order:
Map<String, IncreaseDetails> sortedMap = unsortedMap.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(
(Comparator.comparing(IncreaseDetails::getRealIncrease).reversed())))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> a,
LinkedHashMap::new));

Combining Multiple Maps together in Pig

I am using pig for the first time. I've gotten to the point where I have exactly the answer I want, but in a weirdly nested format:
{(price,49),(manages,"1d74426f-2b0a-4777-ac1b-042268cab09c")}
I'd like the output to be a single map, without any wrapping:
[price#49, manages#"1d74426f-2b0a-4777-ac1b-042268cab09c"]
I've managed to use TOMAP to get this far, but I can't figure out how to merge and flatten it away.
{([price_specification#{"amount":49,"currency":"USD"}]),([manages#"newest-nodes/1d74426f-2b0a-4777-ac1b-042268cab09c"])}
How should I be going about this?
Unfortunately, there are no built-in functions to do this for you. You'll have to write your own UDF. Fortunately, this is a simple one.
The exec method would just go something like:
public Map<String, Object> exec(Tuple input) {
Map<String, Object> m = new HashMap<String, Object>();
for (int i = 0; i < input.size(); i++)
m.putAll((Map<String, Object>) input.get(i));
return m;
}
The UDF could take any number of maps as arguments.
Note that if two or more maps share a key, then the final one encountered will be the one that is kept and the others get overwritten.

Map Support in Shell Scripting

I am new in Shell Scripting, however i am friendly with Java Maps. I Just wanted to know that how can i use Map facility in Shell Scripting. Below is the facility i need to use in shell-
HashMap<String, ArrayList<String>> users = new HashMap<String, ArrayList<String>>();
String username = "test_user1";
String address = "test_user1_address";
String emailId = "test_user1_emailId";
ArrayList<String> values = new ArrayList<String>();
values.add(address);
values.add(emailId);
users.put(username, values);
String anotherUser = "test_user2";
if (users.containsKey(anotherUser)) {
System.out.println("Do some stuff here");
}
In short, i want to use a Map, which has String as key, either Vector or ArrayList as value (otherwise i have live with Arrays instead of ArrayList and manually take care of indexes) , put method to insert and one more method to check the presence of the key in the existing Map.
The above code is a sample code.
Thank you in advance.
bash does not support nested structures like this. Either use separate variables for each array, or use something more capable such as Python.

Resources