How to initialize a two column arraylist? - java

I need to create a List that records two columns {int, String}. I think ArrayList is what I need but I cant get my head around it. I pulled the Strings from a database and the int is the index value which I need to identify the strings position for later.
List<List<String>> strArray = ArrayList<List<String>>;
then could I do something like strArray.add().add() for each row I pull from the database?

I think you should use a HashMap with int as key and String as value if your int values are going to be unique.
Map<Integer,String> myMap = new HashMap<Integer,String>();
myMap.put(1,"ABC");
Note that as Map is a collections and java collections do not store primitive like int, they store objects so you have to use Integer wrapper class for your int values.
Refer this link Why can Java Collections not directly store Primitives types?

Another approach would be to make a custom object:
Class CustomObject {
int value1;
String value2;
CustomObject(int v1, String v2) {
value1 = v1;
value2 = v2;
}
}
And then use it:
List<CustomObject> myList = new ArrayList<CustomObject>();
CustomObject o1 = new CustomObject(1, "one");
myList.add(o1);
// etc.
If the int values are unique and you want to consider them keys, then a Map would work as others have suggested.

If you need just two values you can use native Pair class
List<Pair> mPairs = new ArrayList<Pair>();
Pair pair = new Pair(123,"your string");
mPairs.add(pair);
This will be a good decision if you int values are not unique and so you can not use HashMap

If your IDs are not unique, you still can use Map :
Map<Integer, String> map = new IdentityHashMap<Integer, String>();
map.put(new Integer(1), "string");
IdentityHashMap - use native hashCode implemetation for each OBJECT, so you don't need unique IDs, but you MUST create ALL Integers via operator 'new', and don't use autoboxing, because there is some cache mechanism.
Also there is JVM parameter, which controlls cache size '-XX:AutoBoxCacheMax='.
But using this parameter you can't disable cache, if you set size to the zero, then cache will ignore it and use default: [-128; 127].
This parameter is only for Integers, there is no such kind of parameter for Long.
UPDATE
Also for non unique keys you could use some sort of multimap:
Map> map
And store in it your values with nonunique keys:
map.put(1, new ArrayList<String>());
map.get(1).add("value1");
map.get(1).add("value2");
You can use HashMap for that for example.
Also you can find MultiMap implementation in google-collections: 'guava'.

I think you may wrap the int and string in a class, then put the class objects in List.

Map is an object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
I think it would be better if you use Map<Integer,String> where key(Integer) would be the index which will pointing to String value.
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(1,"str1");
map.put(2,"str2");
...

Related

how can we add (long,String) in arraylist?

I need to create a list with values of type - (long,String)
like -
ArrayList a = new ArrayList();
a.add(1L,branchName);
How can I do this because if I use list It will accept only int,String.
You should note that ArrayList's add(int,String) adds the String element in the given int index (if the index is valid). The int parameter is not part of the contents of the ArrayList.
Perhaps an ArrayList is not the correct choice for you. If you wish to map Long keys to String values, use Map<Long,String>.
Map<Long,String> a = new HashMap<> ();
a.put(1L,branchName);
You can define a custom class, e.g.
class IndexAndBranchName {
long index;
String branchName;
}
and then add instances of this to the ArrayList:
ArrayList<IndexAndBranchName> a = new ArrayList<>();
a.add(new IndexAndBranchName(index, branchName));
Whether you use this approach or something like Eran's depends upon what you need to use the list for subsequently:
If you want to look "branches" up by index, use a Map; however, you can only store a single value per key; you could use a Guava Multimap or similar if you want multiple values per key.
If you simply want all of the index/branch name pairs, you can use this approach.
You can use the below code for your question.
HashMap is also a better option , but if you want only ArrayList then use it.
List<Map<Object, Object>> mylist = new ArrayList<Map<Object, Object>>();
Map map = new HashMap<>();
map.put(1L, "BranchName");
mylist.add(map);

spot the difference between two lists

In java suppose I have 2 lists
List<Object1> list1
List<Object2> list2
object1.getName(); returns a String
object2.getName(); return a String
is there any way to compare the names and get a difference of the two list
those 2 objects are defined in the 3rd party library, and I can't override the equals and compareto methods
I am in favour of googles Guava or commons collections library
but the Sets.symmetricDifference(Set1, Set2) ask for 2 to be passed in,
even i juse Sets.newHashSet(lis1) and Sets.newHashSet(lis2) to create two sets
but still they have difference type of objects in the sets.
or in commons CollectionUtils.disjunction(lis1, list2) the lists still has to contain the same object type
without doing 2 expensive for loops, is there any other way?
First, we'll build two maps, one for each list, mapping names to objects. Then we iterate over the differences between the key sets, processing whichever kind of object had that name. The maps let us avoid scanning through the list looking for the object with that name. (In using Map rather than Multimap, I'm relying on the asker's comment on another answer that within each list, names are unique. If you're still using Java 7, replace the method reference with a Function implementation.)
Map<String, Object1> map1 = Maps.uniqueIndex(list1, Object1::getName);
Map<String, Object2> map2 = Maps.uniqueIndex(list2, Object1::getName);
for (String name : Sets.difference(map1.keySet(), map2.keySet()))
processObject1(map1.get(name));
for (String name : Sets.difference(map2.keySet(), map1.keySet()))
processObject2(map2.get(name));
If all you want to do is build lists or sets of the objects in exactly one list, processObject1 and processObject2 can just add the objects to collections.
uniqueIndex's iteration order is that of the input iterable, and difference returns a SetView with the same iteration order as its first argument, so you can process objects in the order they appeared in the input lists, if that order is relevant to your problem.
Java 8 streams provide basically the same functionality:
Map<String, Object1> map1 = list1.stream().collect(Collectors.toMap(Function.identity(), Object1::getName));
Map<String, Object2> map2 = list2.stream().collect(Collectors.toMap(Function.identity(), Object2::getName));
map1.keySet().stream().filter(n -> !map2.keySet().contains(n)).map(map1::get).forEachOrdered(o1 -> processObject1(o1));
map2.keySet().stream().filter(n -> !map1.keySet().contains(n)).map(map2::get).forEachOrdered(o2 -> processObject1(o2));
Again, you can replace the forEachOrdered call with collect(Collectors.toList()) if you just want to collect the objects.
First you will have to transfor your lists to String based lists:
private static final class FromObject1ToName implements Function<Object1, String> {
#Override
public String apply(Object1 input) {
return input.name;
}
}
The same transformation has to be done for Object2
Then transform the input list:
Collection<String> transformed = Collections2.transform(list1, new FromObject1ToName());
//list1 is a List on Object1
Then create the multiset:
Multiset<String> multiset1 = HashMultiset.create();
multiset1.addAll(transformed);
Then simply do :
Multisets.difference(multiset1, multiset2) // multiset1 is from Object1 and multiset2 is from Object2
This will give you the difference and how many times it differes
If you need to know just the differences, then do the same transform, then load the Collection of strings in a Set adn then do Sets.symmetricDifference
Using Guava, try this. It works for me ->
Multisets.difference(multiset1,multiset2);
How to convert ArrayList to Multiset.
List x = new ArrayList();
x.add(3);.....
Multiset newX = HashMultiset.create();
newX.addAll(x);

Map Entry conversion with Map Tree

So what I have been trying to do is use a TreeMap I previously had and apply it to this method in which I convert it into a set and have it go through a Map Entry Loop. What I wish to do is invert my previous TreeMap into the opposite (flipped) TreeMap
'When I run my code, it gives me a comparable error. Does this mean I have to implement the comparable method? I convereted the arrayList into an Integer so I thought the comparable method would support it. Or is it just something wrong with my code
Error: Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Comparable
Overview: Originally, my intended purpose for the program was to make a Treemap that read from a text document and specifically found all the words and the index/rows of where the words were located. Now I wish to make a "top ten" list that contains the most used words. I wanted to "flip" my treemap so that the integer values would be what would be put in order and the string would follow
public static void getTopTenWords(TreeMap<String, ArrayList<Integer>> map) {
Set<Map.Entry<String, ArrayList<Integer>>> set = map.entrySet();
TreeMap<Integer, String> temp = new TreeMap<Integer, String>();
int count = 1;
for(Map.Entry<String, ArrayList<Integer>> entry : set){
if(temp.containsKey(entry.getValue())) {
Integer val = entry.getValue().get(count);
val++;
temp.put(val, entry.getKey());
}
else {
temp.put(entry.getValue().get(count), entry.getKey());
}
count++;
}
}
Now I wish to make a "top ten" list that contains the most used words.
I wanted to "flip" my treemap so that the integer values would be what
would be put in order and the string would follow
Note that a Map contains only unique keys. So, if you try to keep your count as key, then you would need to put it in your Map by creating a new object with new Integer(count).
If you put your count in Map like: - map.put(2, "someword"), then there are chances that your previous count value gets overwritten, because Integer caches the values in range: - [-128 to 127]. So, the integer values between these range will be interned if you don't create a new object. And hence two Integer with value say 2 will point to same Integer object, and hence resulting in duplicate key.
Secondly, in your code: -
if (temp.containsKey(entry.getValue()))
using the above if statement, you are comparing an ArrayList with an Integer value. temp contains key which are integers. And values in entry are ArrayList. So, that will fail at runtime. Also, since your orginal Map contains just the location of the word found in the text file. So, just what you need to do is, get the size of arraylist for each word, and make that a key.
You would need to modify your code a little bit.
public static void getTopTenWords(TreeMap<String, ArrayList<Integer>> map) {
Set<Map.Entry<String, ArrayList<Integer>>> set = map.entrySet();
TreeMap<Integer, String> temp = new TreeMap<Integer, String>();
for(Map.Entry<String, ArrayList<Integer>> entry : set) {
int size = entry.getValue().size();
int word = entry.getKey();
temp.put(new Integer(size), word));
}
}
So, you can see that, I just used the size of the values in your entry set. And put it as a key in your TreeMap. Also using new Integer(size) is very important. It ensures that every integer reference points to a new object. Thus no duplication.
Also, note that, your TreeMap sorts your Integer value in ascending order. Your most frequent words would be somewhere at the end.

How to sort a map

I have a Map to sort as follows:
Map<String, String> map = new HashMap();
It contains the following String keys:
String key = "key1.key2.key3.key4"
It contains the following String values:
String value = "value1.value2"
where the key and value can vary by their number of dot sections from key1/value1 to key1.key2.key3.key4.key5/value1.value2.value3.value4.value5 non-homogeneously
I need to compare them according to the number of dots present in keys or in values according to the calling method type key / value :
sortMap(Map map, int byKey);
or
sortMap(Map map, int byValue);
The methods of course will return a sorted map.
Any help would be appreciated.
There is no way to impose any sort of order on HashMap.
If you want to order elements by some comparison on the keys, then use a TreeMap with some Comparator on the keys, or just use their default Comparable ordering.
If you want to order by the values, the only real option is to use a LinkedHashMap, which preserves the order that entries were put into the map, and then to sort the entries before inserting them into the map, or perhaps some non-JDK Map implementation. There are dirty hacks that make a key comparator that actually secretly compares the values, but these are dangerous and frequently lead to unpredictable behavior.
For starters, you will need to be using an instance of SortedMap. If the map doesn't implement that interface, then it has an undefined/arbitrary iteration order and you can't control it. (Generally this is the case, since a map is a way of associating values with keys; ordering is an auxiliary concern.)
So I'll assume you're using TreeMap, which is the canonical sorted map implementation. This sorts its keys according to a Comparator which you can supply in the constructor. So if you can write such a comparator that determines which is the "lower" of two arbitrary keys (spoiler alert: you can), this will be straightforward to implement.
This will, however, only work when sorting by key. I don't know if it makes much sense to sort a map by value, and I'm not aware of any straightforward way to do this. The best I can think of is to write a Comparator<Map.Entry> that sorts on values, call Map.getEntrySet and push all the entries into a list, then call Collections.sort on the list. It's not very elegant or efficient but it should get the job done if performance isn't your primary concern.
(Note also that if your keys aren't immutable, you will run into a lot of trouble, as they won't be resorted when externally changed.
You should use a TreeMap and implement a ValueComparator or make the key and value objects that implement Comparable.
Must be a duplicate here...
edit: duplicate of (to name just one) Sort a Map<Key, Value> by values (Java)
I did it by the following:
#SuppressWarnings({ "unchecked", "rawtypes" })
public static Map sortMap(Map unsortedMap) {
List list = new LinkedList(unsortedMap.entrySet());
// sort list based on comparator
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
String value1 = (String)((Map.Entry) (o1)).getValue();
String value2 = (String)((Map.Entry) (o2)).getValue();
// declare the count
int count1 = findOccurances(value1, '.');
int count2 = findOccurances(value2, '.');
// Go to thru the comparing
if(count1 > count2){
return -1;
}
if(count1 < count2){
return 1;
}
return 0;
}
});
// put the sorted list into map again
Map sortedMap = new LinkedHashMap();
for (Iterator it = list.iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
With the following helper method:
private static int findOccurances(String s, char chr) {
final char[] chars = s.toCharArray();
int count = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == chr) {
count++;
}
}
return count;
}
Here, I can put some switch on the comparing part with an additional int argument to change between asc/desc.
I can change between values and keys through a switch of another int argument value to get my answer.

How do I sort elements in a hash table in alphabetical order?

How do I sort hash table elements alphabetically? For example, my elements are:
cijfercode, Zweeds, Doorloper, Kruizword, Crypto, Woordzoker
edit: I also got a solution for sorting the hashtable elements. Here is the solution:
java.util.Vector vec = new java.util.Vector(hashtableList.keySet());
Collections.sort(vec);
If these "elements" are keys you can store them in a TreeMap, which will produce a consistent order based on the natural ordering of the keys. Note you don't need to do much except create a new map with the old map passed to the constructor:
Map<String,?> map = ?
Map<String,?> orderedMap = new TreeMap<String,?>(map);
Then, iterate like normal:
for(String key : orderedMap.keys()){
}
If your "elements" are values, then you can insert them as keys into a TreeMap keeping track of the original keys, read the sorted order of values as before (basically creating an inverted index):
Map<?,String> map = ?
Map<String,List<?>> orderedVals = new TreeMap<String,List<?>>();
for(Entry<?,String> map : map.entrySet()){
List<?> keys = orderedVals.get(map.getValue());
if(keys == null){
keys = new ArrayList<?>();
orderedVals.put(map.getValue(), keys);
}
keys.add(map.getKey());
}
// now orderedVals has keys in sorted order
for(String val : orderedVals.keys()){
}
Of course, if you're not actually using anything related to the fact these things are in a "hashtable" (I read this as something implementing Map), then you can load up a List of your choosing, and sort it:
List<String> list = new ArrayList<String>(map.values()); // or use map.keys()
Collections.sort(list);
If you're not happy with the default sort order for String, feel free to write your own comparator:
Collections.sort(list, new Comparator<String>(){
public int compare(String left, String right){
return // your impl
}
});
compare must return a negative integer when the left comes first, 0 if left and right are the same, and a positive integer if right comes first.
Mark Elliot's idea is correct. I don't like the whole Map<?, List<?>> idea though; I've been far too spoilt on Guava. So here's a Guava version of the same idea:
SortedSetMultimap<String, ?> sorted = Multimaps.invertFrom(
Multimaps.forMap(map), TreeMultimap.create());
for (Map.Entry<String, ?> entry : sorted.entries()) {
// ...
}
This is, like, a third of the size of Mark's code. :-)
java.util.Vector vec =new java.util.Vector(hashtableList.keySet());
Collections.sort(vec);
Please check http://discuss.joelonsoftware.com/default.asp?joel.3.19588.13 for an interesting discussion on this.
Consider http://download.oracle.com/javase/1.4.2/docs/api/java/util/TreeMap.html too.

Categories