I have several objects I want to store in an arrayList that represents a single assembly language instruction (eg Add, Jump, etc). The objects in each ArrayList are constant for a given instruction, so I just need to load each of the objects for a given instruction into the proper arrayList once at load time.
The tedious part is that I need to name each of the objects before they're added to the arrayList:
static {
...
ArrayList<CodeFrag[]> intIntGtrEqlProtoCode = new ArrayList<CodeFrag[]>();
...
intIntGtrEqlProtoCode.add(intIntGtrEqlInst1);
CodeFrag[] intIntGtrEqlInst2 = {Subtract};
intIntGtrEqlProtoCode.add(intIntGtrEqlInst2);
CodeFrag[] intIntGtrEqlInst3 = {Duplicate};
...
}
I have a feeling like there is a way to avoid doing all this extremely tedious naming. Can someone point it out to me?
You could do something like this:
CodeFrag[] arr = {Subtract, Duplicate, Foo, Bar};
for (CodeFrag c : arr)
intIntGtrEqlProtoCode.add(new CodeFrag[]{c});
Also, if all of the arrays have length 1, couldn't you replace it with a List<CodeFrag>? Then you could just do
intIntGtrEqlProtoCode = new ArrayList<CodeFrag>(Arrays.asList(Subtract, Duplicate, Foo, Bar));
Related
For instance I have two Arraylists with different data types.
ArrayList<Integer> intValues = new ArrayList<Integer>();
intValues.add(1);
intValues.add(2);
intValues.add(3);
ArrayList<String> strValues = new ArrayList<String>();
strValues.add("4");
strValues.add("5");
strValues.add("6");
If both of these lists contained the same data type objects, I would easily call addAll function;
intValues.addAll(intValues2);
But of course if I try to call addAll function with these different type lists, compiler warns me with incompatible types: ArrayList cannot be converted to Collection<? extends Integer> warning.
So I have to create a bad solution like;
for(String s: strValues)
{
intValues.add(Integer.parseInt(s));
}
Is there a better way to do this, I mean, creating a class which implements List, overriding addAll function etc. so I will be able to call;
intValues.addAll(strValues);
And intValues list will contain 1,2,3,4,5,6.
Edit: I really don't want to store String values in an Integer array, I have to deal with some creepy old code at the moment and I need a Collection to hold some differend kinds of classes, trying to create a Constructor for those objects, this integer-string scenario is just a simple way to introduce my problem.
Let me tell you about my current situation with another integer-string like scenario:
Creepy class A is car, it holds car's weight, price, color, engine type.
Creepy class B is watch, it holds watch's still type, movement type, price, lug size etc.
I am trying to create a holder class, so it will hold those classes and adding a few functions (for example, overriding compare method makes the holder class to compare prices of different classes).
Now I think I have to create a HolderHolder class which implements List so I can call holderHolder.addAll(carsList) and holderHolder.addAll(watchesList), and it will hold these as Holder objects and yes, this does not look pretty.
You act as if what you want is self-evident and logical. It really isn't. "4" and 4 are entirely unrelated, and expecting that your list of integers now has a value 4 when you call addAll with "4" is, as a consequence, as bizarre as expecting your list of movies to gain 'Forrest Gump' when you call .addAll(colorsOfTheRainbow) on that, because in your mind, 'green' is so incredibly similar to 'Forrest Gump', that you might as well assume that. (Here, 'green' is "4" and 'Forrest Gump' is 4).
So let's do some work and make this more sensible:
That 'assumption' (that "4" is so similar to 4, that you want .add("4") to just mean that 4 shows up in your list) needs to encoded, explicitly, in your code. Now it makes sense, and now you can write a function that maps Green to Forrest Gump and use it for that example just the same - we've generalized the principle.
What you're really talking about is a mapping function that maps an element of your List<String> (so.. a String) to a type that your target list is of (Integer), and you then want the operation: Take this list. Map every value in it with my mapping function. Then, add all the mapped values to this other list.
That makes perfect sense.
So, write that.
List<Integer> intValues = ...;
strValues.map(Integer::valueOf).forEachOrdered(intValues::add);
Looks like bad smell.
One bad Solution can be an own implementation of an List with Type Object. But than you have to cast and work with the Classes of the primitive types.
I think i every case you have to parse or cast. That cost to much of performance just for easy call of addAll.
I would think about the incoming data and why they have to be the same but in different types?
Edit:
If i get to know it correct. It is a little bit hard to understand without more detailed infos.
But maybe you can write an mapper class to map thoose old creepy classes in one new class an then you can put these new class in an collection and can compare all by overriding equals.
public class CreepyClassMapper
{
public CreepyClassMapper(Car aCar, Watch aWatch)
{
}
#override
private boolean equals(Object obj)
{
// maybe add an instance check
CreepyClassMapper other = (CreepyClassMapper) object;
// do your compare stuff
return true;
}
}
if i were you, i will create a function like this in util class
public void append(ArrayList<Integer> intValues, ArrayList<String> strValues){
}
I would like to concatenate two array lists as it shows in the answer:
final List<String> l1 = Lists.newArrayList(...);
final List<String> l2 = Lists.newArrayList(...);
List<String> l = new ArrayList<String>() { { addAll(l1); addAll(l2); } };
Is there any non style reason I should not use it this way?
If you are already using Guava, you can do this using the following one-liner:
List<String> l = FluentIterable.from(l1).append(l2).copyInto(new ArrayList<String>());
I personally don't like double braces. This produces new class just for the purpose to initialize it in different way. New class means bigger target jar file, more memory is necessary for JVM to store classes, bigger inheritance table for JIT compiler, etc. This can become significant if you use such approach everywhere. If you return this ArrayList to another component and your current component is not used anymore (for example, you are using OSGi or other module system), you may end up having hanging ClassLoader which is linked only by this anonymous class. Also if you care about serialization, you should declare serialVersionID in this new class. Even if you don't care, you may have a warning about this.
Well, first of all, it depends on what you wish to do with duplicate elements. This code will keep any duplicates (i.e. if l1 and l2 both contain "someString", l will contain two "someString"), so it's not really a union operation. Calling it a concatenation of two lists would be more accurate.
Other than that, using the "double brace" is actually creating an instance of an anonymous class that extends ArrayList. I think it's a bad code style.
List<String> l = new ArrayList<String>(l1);
l.addAll(l2);
is clearer and is not longer to write.
I am iterating over a List of Lists. In my code listofuserdetailsperAccount is List<List>. I am considering the two methods below, please let me know which way is correct, more efficient and should be followed in java coding.
Way 1-----
for(int i=0;i<=listofuserdetailsperAccount.size();i++){
List list=(List) listofuserdetailsperAccount.get(0);
}
Way 2---
for(int i=0;i<=listofuserdetailsperAccount.size();i++){
List list= new ArrayList();
list=(List) listofuserdetailsperAccount.get(0);
}
I'll go with for each loop
for( List userDetailsPerAccount : listOfUserDetailsPerAccount ) {
//anything you want to do with userDetailsPerAccount
}
Way 1 is better approach than Way 2. In Way 2 List list= new ArrayList(); it will create a extra ArrayList object which does not have any use, which will cause memory consumption for sometime.
And it is also recommended use type specific List<E> so that you dont cast at runtime it will be typesafe.
for(List<E> list : listOfUserDetailsPerAccount){
...
}
In Java 5 and above use for-each.
You have a couple of problems here, with both proposed solutions.
Your List<List> listofuserdetailsperAccount object is not properly typed, as the inner List is a raw type, something to be avoided. Assuming your inner list holds UserDetail objects, your list of lists should be of type List<List<UserDetail>>.
You don't use the for-each loop syntax to iterate over a List, which is Iterable.
for(List<UserDetail> innerList : listofuserdetailsperAccount)
In Way 2 you initialize List to a new ArrayList (which is a raw type, it should be new ArrayList<>() if you needed this) and then promptly overwrite this value with the contents of your outer list. This means you ask Java to construct a new object that is then immediately cleaned up by the garbage collector, unused. This is wasteful and unnecessary.
In summary, you likely want to do:
List<List<UserDetail>> listofuserdetailsperAccount = // initialize your list
for(List<userDetail> innerList : listofuserdetailsperAccount) {
// do work with your innerList now
}
You commented (tidied up):
So while initializing I am doing something like this now, can you please let me know if this is correct:
List<List<String>> listofAccountdetailsLoggedinUser = null;
listofAccountdetailsLoggedinUser = new ArrayList<List<String>>();
OR I should not put it as null and directly create an object like this:
List<List<String>> listofAccountdetailsLoggedinUser =
new ArrayList<List<String>>();
That is the right track, but you do not need to initialize the variable to null. It doesn't hurt anything, since it doesn't construct an unnecessary object, but there's no reason to - you can declare and initialize the variable in one line, like you do in your second example.
Additionally, you don't need to specify the type of the ArrayList on the right hand side, simply use the diamond operator <>, like so:
List<List<String>> listofAccountdetailsLoggedinUser = new ArrayList<>();
Also, consider a shorter variable name, there's no need to use such a long one, and it's no fun to type :)
Is it possible to create a HashMap whose key is an array of integers?
I´m accustomed to use Python and just recently I began working with Java. In my job I need to create a HashMap with keys like:
map.put([5,2], 1);
map.put([3,2], 0);
and so on. I´m using it to later on test if a pair of those numbers are present in the map, if yes, then do something, if not, continue.
To do so I tried the following:
Map<Array, Boolean> test = new HashMap<Array, Boolean>();
int[] a1 = {5,2};
test.put(a1, true);
Eclipse gives the message ("The arguments are not applicable to int[]..."). But any configuration I´ve done I get some error.
I tried using ArrayList, Objects inside the map, nested HashMap and so on but none worked (in python it´s very easy, I´d just write dict[(5,2)] = 1, so I imagine in Java there´s something simple like that). I was suggested to transform the numbers into Strings and add a colon between then, like:
map.put("5:2", 1);
and later on I break the string again but if this is the solution I´ll go back to Python ;)!!
Probably this is a very simple question but I couldn´t find the answer, hope you can help me.
Thanks in advance!
If you want to check for the existance of your entry, you can use a Set (a useful concrete implementation is HashSet.
final Set<List<Integer>> population;
population = new HashSet<List<Integer>>();
population.add(Arrays.asList(1, 2));
if (population.contains(Arrays.asList(1, 2)))
{
...
}
You can use an List as I have done above - but that doesn't guarantee that all your lists are exactly two elements long (if that is indeed a constraint). To make it a bit more robust, you could create your own class to represent the tuple. If you do, make sure you implement equals() and hashCode() (here's an article explaining good practice).
Arrays.asList() is a useful way of creating a list in-line in the code. A more general list is an ArrayList.
The simplest thing would be a Map<List<Integer>, Boolean> -- or even just a Set<List<Integer>>, since you don't care about the value as much as whether the key is there.
The more java-y solution would be some class that represents the two ints:
public class Coordinate { // or whatever
private final int x;
private final int y;
// constructor and overrides for equals, hashCode and toString
}
Then have a Set<Coordinate>.
This is considered more idiomatically Java because the class name tells you exactly what this set is for -- and enforces that it's used that way. A Set<List<Integer>>, on the other hand, could be lots of things: coordinates, lottery pickings, SSNs for people in a given department, credit cards for a payment... you the programmer have no way of knowing just by looking at the type, and it's easy for a set of numbers that means on thing to be accidentally used in another context. A Set<Coordinate> can't be anything other than a set of coordinates.
This works:
Map<List<Integer>,Boolean> map = new HashMap<>();
map.put( Arrays.asList( new Integer(1), new Integer(2) ), false );
map.put( Arrays.asList( 4, 5 ), true ); // Integer type is inferred and ints are autoboxed
map.get( Arrays.asList( 1, 2 ) ); // gets the Boolean object for "false"
Actually java is a lot less expressive than python so you'll have to write a bit more code.
I think you need to use a map with an ArrayList in the following way:
ArrayList al = map.get("key");
if (al == null) {
al = new ArrayList();
map.put("key", al)
}
al.add(some_object);
You also may use the array as the key (as you asked for), probably you want an immutable array. The key for the hash map to work is use some object that has a good implementation of equals and hashCode.
This is the way that it is done in java, you may use any kind of collection though, Sets are more common.
Cheers!
Can someone explain what the following does?
private HashSet nodes[];
nodes = new HashSet[21];
I'm a little confused... in the difference between
private HashSet nodes = new HashSet;
and the above, particularly in terms of the square brackets syntax. Is this an array of HashSets? Because normally I'm used to seeing
int[] myarray = new int[21];
Or something like that.
They're just alternatives - both are valid, unfortunately.
Heck, even this would be valid:
int[] bad [] = null;
That's equivalent to
int[][] bad = null;
Don't do this, obviously :)
From section 10.2 of the JLS:
The [] may appear as part of the type at the beginning of the declaration, or as part of the declarator for a particular variable, or both.
And
We do not recommend "mixed notation" in an array variable declaration, where brackets appear on both the type and in declarators.
Basically, use the form that keeps all the type information in one place - the form you're used to. That's the overwhelmingly idiomatic form.
private HashSet nodes = new HashSet;
is not valid Java. Unlike JavaScript, the new operator in Java always requires a parenthesized argument list.
private HashSet nodes = new HashSet(21);
differs from
private HashSet[] nodes = new HashSet[21];
in that the former constructs one HashSet set that initially has space enough for 21 set items while the latter is an array of 21 null values that can be filled with references to sets.
private HashSet nodes[];
declares a member variable that can refer to any array whose elements are of type HashSet.
nodes = new HashSet[21];
creates an array with space for 21 HashSet references and assigns it to that member variable.
Remember that in Java, unlike in C, HashSet[21] is not a type so you can't just allocate space for an array in Java by doing
int[21] myints;
At some point you have to create an array via
new <type>[size],
the abbreviated syntax new <type> { element0, element1, element2, ... },
or reflectively via java.lang.reflect.Array.newInstance.
Yes, it is an array of HashSets.
HashSet nodes[];
is the same as
HashSet[] nodes;
The difference in where you place the brackets only becomes important when you use commas to declare a bunch of variables at a time:
HashSet[] alpha, bravo, charlie; // Three arrays of hashsets
HashSet delta[], echo, foxtrot; // One array (delta) and two hashsets (echo and foxtrot)
In Java, the declaration
private HashSet nodes[];
is equivalent to the declaration
private HashSet[] nodes;
It can be pronounced "an array of HashSets" or "a HashSet array."