Array Length in Java - Performance [duplicate] - java

This question already has answers here:
What is the Cost of Calling array.length
(8 answers)
Java native array lengths
(6 answers)
Closed 9 years ago.
Let's say I create an array of ints with length 10, i.e.
int[] array = new int[10];
At some point in my code, I want to compare the value of an int variable, let's call it var, with the length of the array.
I would like to know if this piece of code:
if(var == array.length) { // stuff }
and this piece of code:
if(var == 10) { // stuff }
which do exactly the same thing, have also the same performance.
In other words, I would like to know the internal mechanics that the JVM (?) uses to find the length of the array (I don't say "to return" since length is a field, not a method). Does it make use of iteration? Because if it does, then the 2nd piece of code would be faster than the 1st one.
EDIT: Similar question regarding array.length cost (even though focusing more to its use in for loops):
What is the Cost of Calling array.length

.length is a property, so it would not do iteration for sure. Still, the value of the property is, naturally, fetched at runtime, meaning that the second solution will be a little bit faster (as this is comparison with constant).
Still the first implementation is far more preferable:
This makes your code quite more maintainable
You can alter the length of the array only at one place
You will never feel the performance difference unless you pass through this if litterally millions of times in a second.
EDIT By the way you can yourself tell this is a property - there are no braces after the call. I at least do not know of a way in java to make property access do additional computation, but just retrieving its value.

.length is a property of the array, not a function. Thus, the result would be available immediately, with no iteration necessary.

From the Java Doc
The members of an array type are all of the following:
The public final field length, which contains the number of components
of the array. length may be positive or zero.
length is an final field of array, so no iterations are required while writing following code.
if(var == array.length) { // stuff }
And it is good coding practice indeed.

The length property of an array is extracted in constant (O(1)) time - there is no iteration needed. It's also good practice to use this.

Related

Efficient way for checking if a string is present in an array of strings [duplicate]

This question already has answers here:
How do I determine whether an array contains a particular value in Java?
(30 answers)
Closed 2 years ago.
I'm working on a little project in java, and I want to make my algorithm more efficient.
What I'm trying to do is check if a given string is present in an array of strings.
The thing is, I know a few ways to check if a string is present in an array of strings, but the array I am working with is pretty big (around 90,000 strings) and I am looking for a way to make the search more efficient, and the only ways I know are linear search based, which is not good for an array of this magnitude.
Edit: So I tried implementing the advices that were given to me, but the code i wrote accordingly is not working properly, would love to hear your thoughts.`
public static int binaryStringSearch(String[] strArr, String str) {
int low = 0;
int high = strArr.length -1;
int result = -1;
while (low <= high) {
int mid = (low + high) / 2;
if (strArr[mid].equals(str)) {
result = mid;
return result;
}else if (strArr[mid].compareTo(str) < 0) {
low = mid + 1;
}else {
high = mid - 1;
}
}
return result;
}
Basically what it's supposed to do is return the index at which the string is present in the array, and if it is not in the array then return -1.
So you have a more or less fixed array of strings and then you throw a string at the code and it should tell you if the string you gave it is in the array, do I get that right?
So if your array pretty much never changes, it should be possible to just sort them by alphabet and then use binary search. Tom Scott did a good video on that (if you don't want to read a long, messy text written by someone who isn't a native english speaker, just watch this, that's all you need). You just look right in the middle and then check - is the string you have before or after the string in the middle you just read? If it is already precisely the right one, you can just stop. But in case it isn't, you can eliminate every string after that string in case it's after the string you want to find, otherwise every string that's before the just checked string. Of course, you also eliminate the string itself if it's not equal because - logic. And then you just do it all over again, check the string in the middle of the ones which are left (btw you don't have to actually delete the array items, it's enough just to set a variable for the lower and upper boundary because you don't randomly delete elements in the middle) and eliminate based on the result. And you do that until you don't have a single string in the list left. Then you can be sure that your input isn't in the array. So this basically means that by checking and comparing one string, you can't just eliminate 1 item like you could with checking one after the other, you can remove more then half of the array, so with a list of 256, it should only take 8 compares (or 9, not quite sure but I think it takes one more if you don't want to find the item but know if it exists) and for 65k (which almost matches your number) it takes 16. That's a lot more optimised.
If it's not already sorted and you can't because that would take way too long or for some reason I don't get, then I don't quite know and I think there would be no way to make it faster if it's not ordered, then you have to check them one by one.
Hope that helped!
Edit: If you don't want to really sort all the items and just want to make it a bit (26 times (if language would be random)) faster, just make 26 arrays for all letters (in case you only use normal letters, otherwise make more and the speed boost will increase too) and then loop through all strings and put them into the right array matching their first letter. That way it is much faster then sorting them normally, but it's a trade-off, since it's not so neat then binary search. You pretty much still use linear search (= looping through all of them and checking if they match) but you already kinda ordered the items. You can imagine that like two ways you can sort a buncha cards on a table if you want to find them quicker, the lazy one and the not so lazy one. One way would be to sort all the cards by number, let's just say the cards are from 1-100, but not continuously, there are missing cards. But nicely sorting them so you can find any card really quickly takes some time, so what you can do instead is making 10 rows of cards. In each one you just put your cards in some random order, so when someone wants card 38, you just go to the third row and then linearly search through all of them, that way it is much faster to find items then just having them randomly on your table because you only have to search through a tenth of the cards, but you can't take shortcuts once you're in that row of cards.
Depending on the requirements, there can be so many ways to deal with it. It's better to use a collection class for the rich API available OOTB.
Are the strings supposed to be unique i.e. the duplicate strings need to be discarded automatically and the insertion order does not matter: Use Set<String> set = new HashSet<>() and then you can use Set#contains to check the presence of a particular string.
Are the strings supposed to be unique i.e. the duplicate strings need to be discarded automatically and also the insertion order needs to be preserved: Use Set<String> set = new LinkedHashSet<>() and then you can use Set#contains to check the presence of a particular string.
Can the list contain duplicate strings. If yes, you can use a List<String> list = new ArrayList<>() to benefit from its rich API as well as get rid of the limitation of fixed size (Note: the maximum number of elements can be Integer.MAX_VALUE) beforehand. However, a List is navigated always in a sequential way. Despite this limitation (or feature), the can gain some efficiency by sorting the list (again, it's subject to your requirement). Check Why is processing a sorted array faster than processing an unsorted array? to learn more about it.
You could use a HashMap which stores all the strings if
Contains query is very frequent and lookup strings do not change frequently.
Memory is not a problem (:D) .

about java recursion to create combination of string

The question was asking me to return set containing all the possible combination of strings made up of "cc" and "ddd" for given length n.
so for example if the length given was 5 then set would include "ccddd" and "dddcc".
and length 6 would return set containing "cccccc","dddddd"
and length 7 would return set contating "ccdddcc","dddcccc","ccccddd"
and length 12 will return 12 different combination and so on
However, set returned is empty.
Can you please help?
"Please understand extremeply poor coding style"
public static Set<String> set = new HashSet<String>();
public static Set<String> generateset(int n) {
String s = strings(n,n,"");
return set; // change this
}
public static String strings(int n,int size, String s){
if(n == 3){
s = s + ("cc");
return "";}
if(n == 2){
s = s + ("ddd");
return "";}
if(s.length() == size)
set.add(s);
return strings(n-3,size,s) + strings(n-2,size,s);
}
I think you'll need to rethink your approach. This is not an easy problem, so if you're extremely new to Java (and not extremely familiar with other programming languages), you may want to try some easier problems involving sets, lists, or other collections, before you tackle something like this.
Assuming you want to try it anyway: recursive problems like this require very clear thinking about how you want to accomplish the task. I think you have a general idea, but it needs to be much clearer. Here's how I would approach the problem:
(1) You want a method that returns a list (or set) of strings of length N. Your recursive method returns a single String, and as far as I can tell, you don't have a clear definition of what the resulting string is. (Clear definitions are very important in programming, but probably even more so when solving a complex recursive problem.)
(2) The strings will either begin with "cc" or "ddd". Thus, to form your resulting list, you need to:
(2a) Find all strings of length N-2. This is where you need a recursive call to get all strings of that length. Go through all strings in that list, and add "cc" to the front of each string.
(2b) Similarly, find all strings of length N-3 with a recursive call; go through all the strings in that list, and add "ddd" to the front.
(2c) The resulting list will be all the strings from steps (2a) and (2b).
(3) You need base cases. If N is 0 or 1, the resulting list will be empty. If N==2, it will have just one string, "cc"; if N==3, it will have just one string, "ddd".
You can use a Set instead of a list if you want, since the order won't matter.
Note that it's a bad idea to use a global list or set to hold the results. When a method is calling itself recursively, and every invocation of the method touches the same list or set, you will go insane trying to get everything to work. It's much easier if you let each recursive invocation hold its own local list with the results. Edit: This needs to be clarified. Using a global (i.e. instance field that is shared by all recursive invocations) collection to hold the final results is OK. But the approach I've outlined above involves a lot of intermediate results--i.e. if you want to find all strings whose length is 8, you will also be finding strings whose length is 6, 5, 4, ...; using a global to hold all of those would be painful.
The answer to why set is returned empty is simply follow the logic. Say you execute generateset(5); which will execute strings(5,5,"");:
First iteration strings(5,5,""); : (s.length() == size) is false hence nothing added to set
Second iteration strings(2,5,""); : (n == 2) is true, hence nothing added to set
Third iteration strings(3,5,""); : (n == 3) is true, hence nothing added
to set
So set remains un changed.

Which one is preferable? [duplicate]

This question already has answers here:
Time complexity for java ArrayList
(6 answers)
Closed 6 years ago.
I am getting arraylist.get(i) every time a loop executes more than three times within the loop.
Is it advisable or shall I store it in separate variable then use it again and again? Which one is preferable performance wise?
Setting it to a variable is slightly more efficient. Accesing arrayList.get (I) is O (1) but still costs something eventhough it is really minor and insignificant.
Setting it to a variable is more readable in my opinion.
It's always a good approach to write readable and maintainable code. Since you question is very broad so expect broad answers as well.
List<Integer> integerList = new ArrayList<>();
for (int i=0;i<integerList.size();i++) {
Integer integerValue = integerList.get(i);
// make sure integerValue is not null.
// Thanks #Tom for pointing this out
System.out.println (integerValue);
// Do operations
System.out.println (integerValue);
// Do more operations
System.out.println (integerValue);
}
Now this is one time assignment but you can use it at multiple times. Now, for instance, you have to change the logic of program so that you want to get always i+1, it will be easy for you to change only once, not multiple times.
As others mentioned, getting object one time is slightly more efficient. Of course most of times this won't produce any problems and you can't notice any differences.
Logically because it's an O(1) operation, it shouldn't cause any differences at all, but because it calls a function of an object of type ArrayList , It's less cache friendly and direct memory reference maybe needed. Still the difference is very little.
declaring and assigning a variable once like String myString = arraylist.get(i); will be marginally faster than calling arraylist.get(i) multiple times.
Once you've done this you can call any methods on the myString instance.
I assume that arraylist is of type ArrayList<String>.
you may want to include a null check in your loop as well:
for(int i = 0; i < arraylist.size(); i++){
String myString = arraylist.get(i);
if(myString != null){
//any calls to methods on myString
}
}

How do I use ArrayList<Integer>#contains when I only have a BigInteger?

I am pulling data values from a database that returns a List of <Integer>. However, I would like to see if the List contains my BigInteger. Is there a simple way to do this?
I currently have the following code in Java:
ArrayList<Integer> arr = new ArrayList<Integer>() {{add(new Integer(29415));}};
boolean contains = arr.contains(29415); // true
boolean contains2 = arr.contains(new BigInteger("29415")); // false
I'm not sure on an efficient way to do this?
The correct answer will be returned by evaluation of the following:
val != null
&& BigInteger.valueOf(Integer.MIN_VALUE).compareTo(val) < 0
&& BigInteger.valueOf(Integer.MAX_VALUE).compareTo(val) > 0
&& list.contains(val.intValue())
This will correctly solve the question of whether the BigInteger you have is "contained" within the List<Integer>. Note that here we only downcast where necessary. If the val is outside the range of Integer values there is no need to downcast as we know that the value cannot be within the list.
A more relevant question is whether you should actually be using a List<BigInteger> in place of a List<Integer> but that is a different question and not part of the answer to your explicit question
While arshajii provides a solution which works, i would vote against it.
You should never downcast values. You are running in danger of your program producing larger values which translate to invalid values when downcasted. This kind of bug will be super nasty to troubleshoot months later.
If your code works with BigInteger, then you should convert all values from the database into BigInteger. This is an upcast where you cannot loose values.
Overall I would value correctness over efficiency. If at all, I would reconsider your usage of BigInteger (maybe long is fine?) but because you have it, I assume you have a reason for it.
In Java List.contains() uses the equals() method internally and because BigInteger.equals(Integer) returns false, your List.contains() also returns false. Either use the an List<BigInteger> or extract the Int value from BigInteger (as arshajii explained!). Of course, if you really want to search effectively, you should think of a binary search (in a sorted list) or of another data structure like Map.
You can try using BigInteger#intValue():
arr.contains(myBigInteger.intValue())
Note, however, that if myBigInteger is too big to fit into an int, then only the lower 32 bits will be returned (as described in the linked docs). Therefore, you might want to check if myBigInteger is less than or equal to Integer.MAX_VALUE before checking for containment.

Array iteration with static final limits

I have an array:
final int[] exampleArray = new int[ID_DATA_ARRAY_SIZE];
And I can iterate that array several ways, for example:
Way 1:
for (int i = 0; i < exampleArray.length; i++) {
// code where I use 'i' index
}
Way 2:
for (int i = 0; i < ID_DATA_ARRAY_SIZE; i++) {
// code where I use 'i' index
}
Which way is better? Are there any other better ways to do it?
If you don't need i for anything else than extracting the element, then the enhanced for loop looks a bit nicer:
for(int element : exampleArray) {
//code that uses element
}
If you are using i for both accessing the array, and something else, then I would argue Way 1 is best:
for (int i = 0; i < exampleArray.length; i++) {
// code where I use 'i' index
}
The reason is that the next time someone looks at a code, the person will immediately see that you are iterating to the length of the array. If you go for way 2 (using a constant), the reader might wonder if that constant really is the length of your array.
Tackling both performance, and code readability, way 2 is better.
Rated by performance, by using exampleArray.length you are calling upon a "member" variable which requires additional java bytecode to request when compared to calling a "local" variable. But, the difference in performance is extremely minuscule and you would never notice it unless you were making an extreme amount of calculations.
Rated by readability, ID_DATA_ARRAY_SIZE lays out your intent for whomever is reading, which is more important than it may seem. Yet, too many programmers lay out nonsensical or ambiguous variable names, and it makes reading their code lacking in naturalness. Naming variables and functions in a way that makes sense to our minds in an organic way makes the code much simpler to deal with for yourself in the future, and anyone else, making it a good practice.
The fundamental difference in the two approaches, I see is as below:
In Way 1: you use the constant exampleArray.length in the loop condition
In Way 2: you use the constant ID_DATA_ARRAY_SIZE in the loop condition
Obviously way 2 is superior in terms of performance.
This is because you are accessing a constant rather than access member variable of exampleArray object. This advantage is realized in every iteration of the for loop where the value of length member is accessed.
see it is all about personal taste which way you wanna do but whenever you are working with array better to check null for the array and then do your stuff

Categories