Java ArrayList problem (involves valueOf()) - java

So I have this function, combinations, which adds to an arraylist all permutations of a string.
public static void combinations(String prefix, String s, ArrayList PermAttr) {
if (s.length() > 0) {
PermAttr.add(prefix + s.valueOf(s.charAt(0)));
combinations(prefix + s.valueOf(s.charAt(0)), s.substring(1), PermAttr);
combinations(prefix, s.substring(1), PermAttr);
}
}
Now, I have this arrayList tryCK which let us say is {"A","B"}.
I have another arrayList CK which is also {"A","B"}, but it was derived from the combinations function above.
When I do tryCK.equals(CK) it returns true.
But when I put it through a another function I have on both tryCK and CK, for tryCK it returns true and CK it returns false, even though they are exactly the same lists.
So, my question is, does using .valueOf(s.charAt()) change some inner type?
This is super hard to explain but I do not want to post the full code.

First of All, you don't even really need to use valueOf because most always, Java is just fine concatenizing characters to the end of strings.
PermAttr.add(prefix + s.charAt(0));
Second, If you are going to use valueOf, at least reference it from the class String, not an instance of a String object...
PermAttr.add(prefix + String.valueOf(s.charAt(0)));
Third, a better naming convention would be helpful:
permAttr.add(prefix + s.valueOf(s.charAt(0)));
Fourth, there are plenty of ways to check the contents of your ArrayList, try making sure they actually contain the same values instead of assuming they do:
for(String s : CK)
System.out.println(s);
Fifth, you summed up with "So, my question is, does using .valueOf(s.charAt()) change some inner type?" and the answer is:
valueOf(s.charAt(int)) will return a String object. If you were not anticipating a string, then yes, this changes the type of the object. This String functions normally with all other Strings (like the ones you are concatenizing it with) and should do anything a String can do. So if you were expecting a String type, then no, it does not change any type.
Sixth, make sure if you are comparing strings to use the equals() method.
DO NOT USE:
if(s1 == s2)
this will check to see if the reference the same location in memory.
USE
if(s1.equals(s2))
this will check to see if the values of the Strings are the same.
I think that's all I got. GOOD LUCK!

First issue: you're using String.valueOf as if it were an instance method, when it's actually a static method. That leads to very misleading code.
Second issue: you don't have a consistent naming convention. Parameters should generally be camel cased - naming a parameter PermAttr leads to method calls such as:
PermAttr.add(prefix + s.valueOf(s.charAt(0)));
which looks like a static method call in a class called PermAttr.
Third issue: you're using String.valueOf for no reason - you're already using string concatenation, so using just:
prefix + s.charAt(0)
would be fine.
None of those are actually responsible for whatever's wrong (which we can't easily tell without a short but complete example demonstrating the problem) but they are making it harder to understand the code.
I suggest you fix the above issues, and put this into the context of a short but complete program which does demonstrate the problem. It should then be reasonably easy to work out what's wrong.

Related

Using Java 8 Optional for List of String as output

I want to use Optional for a method which returns a List
Lets say the function is
public Output getListOfSomething() {
// In some cases there is nothing to return and hence it makes sense to have return
// type as Optional here
}
Hence the function looks like :
public Optional<List<String>> getListOfSomething() {
// return something only when there is some valid list
}
Now I want to do something if the list is present so something like :
Optional<List<String>> listOfSomething = getListOfSomething();
int size = 0;
listOfSomething.ifPresent(size = listOfSomething.get().size());
I am new to Optional and have gone through the articles about Optional and it seems like this should work however am getting syntax error in my IDE :
method ifPresent is not applicable for the arguments (void).
I wanted to get some help from developers who might be more fluent with lamdas in java 8.
It's important to think about the Semantics here.
Your method could return a List, or "no list".
If it returns a List, it could return an Empty list.
You should ask, "is there a semantic reason to distinguish between an Empty List, and No List?" Sometimes there is a good design reason to make the difference, but it is rare. Think long and hard before deciding that Empty and Null are different in your case. Part of the reason to avoid No List, is that it reduces "special cases" that the client code has to consider. For example, if they have to do something for every item returned, but you could also return null, they have to do a special check for null before going into a for each loop. A for each does nothing if the list is empty.
If a "No List" is distinct from an "Empty List" in your problem domain, then it is sometimes useful to return wrapper class that helps client code distinguish between those conditions, and handle them appropriately. Optional is one such generic class, but your domain may call for something more specific (even if it mimics the functionality of Optional, it might have better semantic definition).
The true functional-programming way is the following:
size = listOfSomething.map(List::size).orElse(0);
But it would be much better to return an empty List instead of Optional.
ifPresent requires a Consumer interface to work. You could do the following:
Optional<List<String>> listOfSomething = getListOfSomething();
Integer[] size = {0};
listOfSomething.ifPresent(list -> size[0]=list.size())
But as stated by Tagir Valeev it would be better to do:
size = listOfSomething.map(List::size).orElse(0);
And it would also be better to return an empty List or even a Stream maybe.

Android: String equals and contains not matching

I'm testing out the JSON functionality for an Android application and have the following JSON object.
{"result":"fail"}
I then use the following code to get my value:
JSONObject jObject = new JSONObject(ReturnValue); //Return value is what's shown above
String r = jObject.getString("result");
Then using the following I don't get a match
if(r.trim() == "fail")
I wrote it out to the screen just to make sure with this:
et.setText("-" + r + "-");
That results in -fail-
I don't understand why this doesn't match. If I used r.Contains it returns true, but I can't use that for my checks.
Use equals .equals instead of ==. This is because of in Java, if you use == you compare the Object pointers to each other. In the source code of String they have overriden the equals method so they instead compare the letters.
You can't override operators in Java.
Also this is general, always use equals for any object comparison if you don't want to check the references you are comparing are actually pointing on the same object in the heap.
Use
if(r.trim().equals("fail"))
to compare Strings.
as others pointed out, in Java == means "exactly the same object", not "an identical object". You can have two, say, SimpleDateFormat objects that are identical, yet if they occupy different places on the heap, they are not the same object. fyi, C# behaves in quite similar way, but manages to hide it from programmers most of the time.
btw, Since you are already writing Java code, it might be a good idea to, you know, study the language a bit. Saves an awful lot of problems later on. A lot of other surprises await for people who try to write C# in Java (like non-static inner classes).

Always avoid in-out parameters in Java?

There's no doubt that in-out parameters leads to confused code since they may increase unexpected/unpredictabled side-effects.
So, many good programmers say :
Avoid in-out parameters for changing mutable method parameters. Prefer to keep parameters unchanged.
For a perfectionist programmer who expects his code to be the most clean and understandable, does this "rule" must be applied in all case ?
For instance, suppose a basic method for adding elements to a simple list, there's two ways :
First way (with in-out parameter):
private void addElementsToExistingList(List<String> myList){
myList.add("Foo");
myList.add("Bar");
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
addElementsToExistingList(myList);
Second way without out parameter :
private List<String> addElementsToExistingList(List<String> originalList){
List<String> filledList = new ArrayList<String>(originalList); //add existing elements
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(addElementsToExistingList(myList));
Pros of second way :
Parameter are not modified => no risk of unexpected side-effects for a new code reader.
Cons of second way :
Very verbose and very less readable ...
Of course, you would tell me that for a code as simple as this one, first way is really more convenient.
But, if we don't consider the difficulty of any concept/code, I juge the second way more logical and obvious for any readers (beginners or not).
However, it violates the CQS principle that consider "command" methods having void return with potential (but allowed since it's the convention) side-effects and "query" methods having a return type and without side-effects.
So, what should a motivate programmer adopt ? Mix of two accorging to the code case ? Or keep the "law" expecting to always avoid in-out parameters...
(Of course, method for adding Element is named for expliciting the example, and would be a bad name choice in real code).
I think the law should be:
Use what is more straight-forward, but always, always document the behavior of your methods extensively.
Your second example is a very nice case where without documentation you would have a guaranteed bug: the name of the method is addElementsToExistingList, but the method does not add elements to the existing list - it creates a new one. A counter-intuitive and misleading name, to say the least...
There is a third way. Wrap List<String> into a class that knows how to add elements to itself:
class ElementList {
private List<String> = new ArrayList<String>();
public void addElements(Element... elements);
}
I like this approach because it keeps the List implementation private. You don't have to worry if someone passes an immutable list to your method or whether parameters are modified. The code is simpler. Long method names like addElementsToExistingList are code smells that an object is trying to do something another object should be doing.
You should always document when mutating an object that is a parameter because otherwise this can have unintended side effects for the caller. In the first case I agree with the others that have commented that the method name is sufficient documentation.
In your second example, the elements that are already present in myList seem to be added twice. In fact you could entirely remove the parameter of the addElementsToExistingList method and rewrite it as:
private List<String> getElements() {
List<String> filledList = new ArrayList<String>();
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(getElements());
Note that this code is not equivalent to your second example because the elements are only added once, but I think this is actually what you intended. This is the style that I usually prefer. This code is easier to understand and more flexible than the first example without adding extra code (it may degrade performance very slightly but this usually isn't a concern). The client of getElements() can now also do other things with the element list besides adding it to an existing collection.
It's fine to change/mutate parameters as long as it's documented. And of course with a method name of "addElementsToExistingList", what else should someone expect? However, as someone previously pointed out, your second implementation returns a copy and doesn't modify the original, so the method name is now misleading. Your first way is a perfectly acceptable way of doing things. The only other additional improvements is to possibly add a true/false value to the return indicating true if only all the elements were added to the list.
In the case of your example the name makes it clear - "addElementsToExistingList" to me seems pretty clearly to hint that you're going to .. er.. you know. But your concern would be justified with a less obvious name.
For example, in ruby this is commonly handled with naming conventions
"a".upcase => gives you the uppercase of the variable, leaves the original unchanged
"a".upcase! => alters the original variable

No reverse method in String class in Java?

Why there is no reverse method in String class in Java? Instead, the reverse() method is provided in StringBuilder? Is there a reason for this? But String has split(), regionMatches(), etc., which are more complex than the reverse() method.
When they added these methods, why not add reverse()?
Since you have it in StringBuilder, there's no need for it in String, right? :-)
Seriously, when designing an API there's lots of things you could include. The interfaces are however intentionally kept small for simplicity and clarity. Google on "API design" and you'll find tons of pages agreeing on this.
Here's how you do it if you actually need it:
str = new StringBuilder(str).reverse().toString();
Theoretically, String could offer it and just return the correct result as a new String. It's just a design choice, when you get down to it, on the part of the Java base libraries.
If you want an historical reason, String are immutable in Java, that is you cannot change a given String if not creating another String.
While this is not bad "per se", initial versions of Java missed classes like StringBuilder. Instead, String itself contained (and still contains) a lot of methods to "alter" the String but since String is immutable, each of these methods actually creates and return a NEW String object.
This caused simple expressions like :
String s = "a" + anotherString.substr(10,5).trim().toLowerCase();
To actually create in ram something like 5 strings, 4 of which are absolutely useless, with obvious performance problems (despite after there has been some optimizations regarding underlying char[] arrays).
To solve this, Sun introduced StringBuilder and other classes that ARE NOT immutable. These classes freely modify a single char[] array, so that calling methods does not need to produce many intermediate String instances.
They added "reverse" quite lately, so they added it to StringBuilder instead of String, cause that's now the preferred way to manipulate strings.
As a side-note, in Scala you use the same java.lang.String class and you do get a reverse method (along with all kinds of other handy stuff). The way it does it is with implicit conversions, so that your String gets automatically converted into a class that does have a reverse method. It's really quite clever, and removes the need to bloat the base class with hundred of methods.
String is immutable, meaning it can't be changed.
When you reverse a String, what's happening is that each letter is switched on it's own, means it will always create the new object each times.
Let us see with example:
This means that for instance Hello becomes as below
elloH lloeH loleH olleH
and you end up with 4 new String objects on the heap.
So think if you have thousands latter of string or more then how much object will be created.... it will be really a very expensive. So too much memory will be occupied.
So because of this String class not having reverse() method.
Well I think it could be because it is an immutable class so if we had a reverse method it would actually create a new object.
reverse() acts on this, modifying the current object, and String objects are immutable - they can't be modified.
It's peculiarly efficient to do reverse() in situ - the size is known to be the same, so no allocation is necessary, there are half as many loop iterations as there would be in a copy, and, for large strings, memory locality is optimal. From looking at the code, one can see that a lot of care was taken to make it fast. I suspect the author(s) had a particular use case in mind that demanded high performance.

is there a performance hit when using enum.values() vs. String arrays?

I'm using enumerations to replace String constants in my java app (JRE 1.5).
Is there a performance hit when I treat the enum as a static array of names in a method that is called constantly (e.g. when rendering the UI)?
My code looks a bit like this:
public String getValue(int col) {
return ColumnValues.values()[col].toString();
}
Clarifications:
I'm concerned with a hidden cost related to enumerating values() repeatedly (e.g. inside paint() methods).
I can now see that all my scenarios include some int => enum conversion - which is not Java's way.
What is the actual price of extracting the values() array? Is it even an issue?
Android developers
Read Simon Langhoff's answer below, which has pointed out earlier by Geeks On Hugs in the accepted answer's comments. Enum.values() must do a defensive copy
For enums, in order to maintain immutability, they clone the backing array every time you call the Values() method. This means that it will have a performance impact. How much depends on your specific scenario.
I have been monitoring my own Android app and found out that this simple call used 13.4% CPU time! in my specific case.
In order to avoid cloning the values array, I decided to simple cache the values as a private field and then loop through those values whenever needed:
private final static Protocol[] values = Protocol.values();
After this small optimisation my method call only hogged a negligible 0.0% CPU time
In my use case, this was a welcome optimisation, however, it is important to note that using this approach is a tradeoff of mutability of your enum. Who knows what people might put into your values array once you give them a reference to it!?
Enum.values() gives you a reference to an array, and iterating over an array of enums costs the same as iterating over an array of strings. Meanwhile, comparing enum values to other enum values can actually be faster that comparing strings to strings.
Meanwhile, if you're worried about the cost of invoking the values() method versus already having a reference to the array, don't worry. Method invocation in Java is (now) blazingly fast, and any time it actually matters to performance, the method invocation will be inlined by the compiler anyway.
So, seriously, don't worry about it. Concentrate on code readability instead, and use Enum so that the compiler will catch it if you ever try to use a constant value that your code wasn't expecting to handle.
If you're curious about why enum comparisons might be faster than string comparisons, here are the details:
It depends on whether the strings have been interned or not. For Enum objects, there is always only one instance of each enum value in the system, and so each call to Enum.equals() can be done very quickly, just as if you were using the == operator instead of the equals() method. In fact, with Enum objects, it's safe to use == instead of equals(), whereas that's not safe to do with strings.
For strings, if the strings have been interned, then the comparison is just as fast as with an Enum. However, if the strings have not been interned, then the String.equals() method actually needs to walk the list of characters in both strings until either one of the strings ends or it discovers a character that is different between the two strings.
But again, this likely doesn't matter, even in Swing rendering code that must execute quickly. :-)
#Ben Lings points out that Enum.values() must do a defensive copy, since arrays are mutable and it's possible you could replace a value in the array that is returned by Enum.values(). This means that you do have to consider the cost of that defensive copy. However, copying a single contiguous array is generally a fast operation, assuming that it is implemented "under the hood" using some kind of memory-copy call, rather than naively iterating over the elements in the array. So, I don't think that changes the final answer here.
As a rule of thumb : before thinking about optimizing, have you any clue that this code could slow down your application ?
Now, the facts.
enum are, for a large part, syntactic sugar scattered across the compilation process. As a consequence, the values method, defined for an enum class, returns a static collection (that's to say loaded at class initialization) with performances that can be considered as roughly equivalent to an array one.
If you're concerned about performance, then measure.
From the code, I wouldn't expect any surprises but 90% of all performance guesswork is wrong. If you want to be safe, consider to move the enums up into the calling code (i.e. public String getValue(ColumnValues value) {return value.toString();}).
use this:
private enum ModelObject { NODE, SCENE, INSTANCE, URL_TO_FILE, URL_TO_MODEL,
ANIMATION_INTERPOLATION, ANIMATION_EVENT, ANIMATION_CLIP, SAMPLER, IMAGE_EMPTY,
BATCH, COMMAND, SHADER, PARAM, SKIN }
private static final ModelObject int2ModelObject[] = ModelObject.values();
If you're iterating through your enum values just to look for a specific value, you can statically map the enum values to integers. This pushes the performance impact on class load, and makes it easy/low impact to get specific enum values based on a mapped parameter.
public enum ExampleEnum {
value1(1),
value2(2),
valueUndefined(Integer.MAX_VALUE);
private final int enumValue;
private static Map enumMap;
ExampleEnum(int value){
enumValue = value;
}
static {
enumMap = new HashMap<Integer, ExampleEnum>();
for (ExampleEnum exampleEnum: ExampleEnum.values()) {
enumMap.put(exampleEnum.value, exampleEnum);
}
}
public static ExampleEnum getExampleEnum(int value) {
return enumMap.contains(value) ? enumMap.get(value) : valueUndefined;
}
}
I think yes. And it is more convenient to use Constants.

Categories