Can you please let me know which version of java below flower bracket ({}) is introduced? what is concept name for this.
Object[] arg = {abc.getAbctNumber()};
here abc is object of java class and getAbcNumber() is a java method. I understand that arg object will be assigned with the value of return value of getAbcNumber() method.
{} is used to specify an array literal. So in your case you're specifying an array of objects with one element.
There is no such thing as a "flower bracket" in java. What you are seeing here, is an array being populated by a method.
You are creating an array with this syntax similar to:
int myarray[] = {1, 2, 3};
which will create an array of three ints. Your array will be created with an object.
This looks like a list initializer (not sure about the terminology, I don't do a lot of Java). In this case arg is an array of type Object and it's being initialized with a single value, which is the result of abc.getAbctNumber().
Consider an initializer with more than one value and it starts to become more clear:
Object[] arg = {
abc.getAbctNumber(),
abc.getSomeOtherNumber(),
abc.getSomethingElse()
};
That would initialize the arg array with three elements, the results of three different methods.
There is nothing called Flower bracket(at least I don't know about that). And in your Object[] arg = {abc.getAbctNumber()}; {} represent an array of one element and that element being an Object that is returned by method getAbctNumber()
Related
I'm learning how to use stream, and I get a problem with this method.
public static String[] inArray(String[] array1, String[] array2) {
return Arrays.stream(array1)
.filter(str -> Arrays.stream(array2).anyMatch(s -> s.contains(str)))
.distinct().sorted().toArray(**String[]::new**);
}
I'm so confused about String[]::new, could you give me a hint?
String[]::new means size -> new String[size].
When Stream#toArray(IntFunction<A[]> generator) is ready to produce an array, it calls generator and passes (generator.apply) the size of the inner collection to get a collection to fill it up.
I would say the existing answers provide some insight but none of them yet talk about IntFunction<R>.
To add to them explain, what it means in the context of Stream.toArray(String[]::new) is that it represents an IntFunction implementation such as :
new IntFunction<String[]>() {
#Override
public String[] apply(int value) {
return new String[value];
}
}
where the code creates a newly allocated String[] of size value and produces the array of that size as an output.
You are right to be confused, because Java isn't really super clear about types vs. classes.
We know that String[] is a type, as you can declare variables of that type:
jshell> String[] s = new String[]{"Hello", "world"}
s ==> String[2] { "Hello", "world" }
However, String[] actually is treated as a class in Java and not just a type:
jshell> s.getClass()
$2 ==> class [Ljava.lang.String;
That funny looking [Ljava.lang.String, representing the type "array of string" shows up in response to the getClass invocation. I agree that it is surprising. But every object in Java has to have a class, and String[] is that class. (In other languages, you might see something like Array<String> which might be a dash clearer. But then Java has type erasure so again, things look a little confusing.)
In your particular case, here's what's going on. You need to be careful with types when making arrays from streams. Naively, you might get:
jshell> Arrays.asList("a", "b").stream().toArray()
$5 ==> Object[2] { "a", "b" }
So we want the version of toArray that gives us an array:
jshell> Arrays.asList("a", "b").stream().toArray((n) -> new String[n])
$7 ==> String[2] { "a", "b" }
That's better! The result type is an array of strings, instead of just an array of obejcts. Now the (n)->new String[n] can be replaced with a method reference for construction. Java allows array types in method references! So we can write:
jshell> Arrays.asList("a", "b").stream().toArray(String[]::new)
$8 ==> String[2] { "a", "b" }
Aside: There are some caveats when using array types in method references like this, such as the requirement that the array type must be reifiable, but I think that's a little beyond what you might have been asking. The TL;DR here is that, by design, Java allows array types in (constructor-like) method references with ::new.
This is a method reference expression see JLS 15.13. The syntax for method references is:
MethodReference:
ExpressionName :: [TypeArguments] Identifier
Primary :: [TypeArguments] Identifier
ReferenceType :: [TypeArguments] Identifier
super :: [TypeArguments] Identifier
TypeName . super :: [TypeArguments] Identifier
ClassType :: [TypeArguments] new
ArrayType :: new
The particular case you are looking at is the last one. In your example, String[] is an ArrayType which means that it consists of a type name followed by one or more [].
There shouldn't be a class named String[] which is very lame and I could not interpret what it is actually meant for.
See above: it is a type specification not a class name. From a syntactic / linguistic perspective, this usage is analogous to:
Class<?> c = String[].class;
or
if (a instanceof String[])
or even
public void myMethod(String[] arg)
(You wouldn't call those "lame" ... would you?)
Now you could have a valid case for saying that it is syntactically unexpected (especially to a pre-Java 8 programmer) to be able to use the new keyword like this. But this unexpected syntax is a consequence of the strong imperative that the designers have to NOT break backwards compatibility when adding new language features to Java. And it is not unintuitive. (At least, I don't think so. When I first saw this construct, is was obvious to me what it meant.)
Now, if they were starting with a clean slate in 2018, a lot of details of the Java language design would be simpler and cleaner. But they don't have the luxury of doing that.
The documentation of Stream#toArray says it exactly:
The generator function takes an integer, which is the size of the desired array, and produces an array of the desired size.
for example:
IntFunction<int[]> factory = int[]::new;
// v--- once `apply(3)` is invoked,it delegates to `new int[3]`
int [] array = factory.apply(3);
// ^--- [0, 0, 0] create an int array with size 3
String[]::new is a method reference expression and it must be assigned/casted to a certain functional interface type at compile time:
A method reference expression is used to refer to the invocation of a method without actually performing the invocation. Certain forms of method reference expression also allow class instance creation (§15.9) or array creation (§15.10) to be treated as if it were a method invocation.
A method reference expression is compatible in an assignment context, invocation context, or casting context with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.
Edit
As #Eugene mentioned in comments below. It's necessary to let you know how and where the stream create an fixed size array to collecting all elements.
The following table is showing the stream how to calculates the array size:
sequential stream - AbstractSpinedBuffer#count
parallel stream
stateless OPs with known/fixed size Spliterator - AbstractConcNode#AbstractConcNode
stateful OPs
fixed size Spliterator - Spliterator#estimateSize
unknown size Spliterator - AbstractConcNode#AbstractConcNode
The following table is showing the stream where to creates a fixed size array by array generator IntFunction:
sequential stream
stateful/stateless OPs with unknown/fixed size Spliterator - SpinedBuffer#asArray
parallel stream
stateless OPs with known/fixed size Spliterator - Nodes#flatten
stateful OPs
fixed size Spliterator - Nodes#collect
unknown size Spliterator - Nodes#flatten
String[]::new
This is lambda for the following method:
public String[] create(int size) {
return new String[size];
}
Your whole stream operation is terminating converting that into an array, that is what you do with the last method toArray(), but an array of what?....
of Strings ( thus String[]::new)
The parameter of toArray(...) is a Functional Interface (namely IntFunction<R> and then String[]::new is defined as the Method Reference or in that case constructor to use that generates an array of the desired type.
See https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html
And https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Adding to the answer of Andrew Tobilko:
"String[]::new means size -> new String[size]"
which, since toArray takes an IntFunction, is similar to:
IntFunction<String[]> generator = new IntFunction<String[]>() {
#Override
public String[] apply(int size) {
return new String[size];
}
};
To convert your stream to another List, you can use:
.collect(Collectors.toList());
If I have an Object instance, say a4, is there a way I could print out the name of the instance?
So with the instance a4, I would like my output to say a4.
Not stalking you I swear!
Short answer: No
Long Answer: Its impossible to get the name of a local variable using the reflection API as it is simply not available to the JVM. Have a look here: Java Reflection: How to get the name of a variable?
Its a hideously messy thing to attempt to do. Why are you trying to do it?
The simple answer is; if you want an object to have a name, give it a name field and add this field to the toString()
Local variables are only available in the debug information of a method. It is possible to read the byte code of a method and reverse engineer a name but this requires an extraordinary amount of work.
Consider
Object a1 = ...
Object b1 = a1;
The same object is referenced by two local variables. An object can be referenced in any number of places. e.g the empty string object is often the most referenced object in a Java program. It can appear in 10Ks places in a normal program.
I'm trying to add an array to a HashMap using a method that is only passed in a HashMap key. I take the key, extract an array already in the HashMap, make a clone of it, and then place that clone in the HashMap using the name of the instance as the key.
Say you pass an array into a method like
public void addArray(int... array) {
At this point the "name" of the reference to the array is array and it will not be anything difference.
What you need is to pass the name you want the array to have as there is no way for a caller to know what the callee used as a local variable. Often a variable has no name in the first place.
addArray(1, 2, 3);
or
addArray(calculateNumbers());
or
int[] nums = { 1, 2, 3 };
addArray(nums);
Note: nums is not actually needed as a local variable can be optimised away. i.e. There is a good chance nums won't even exist at runtime.
What you need to do is
public void addArray(String name, int... array) {
map.put(name, array);
}
In java, I can initialize an array with predefined content either by :
int[] myArr = new int[]{1,2,3};
Or by :
int[] myArr = {1,2,3};
Essentially, is there any difference between these two ways ? Are they completely identical in Java ? Which way is better and why?
In your case there is no difference.
There will be a difference when you are not assigning your array to variable and doing inline creation.
for example, conside there is method, which takes an array as argument.
private void someX(int[] param){
// do something
}
Your case:
someX(myArr); // using some declared array .I.e your case
Now see the difference while calling it in other cases.
someX(new int[] {1,2,3}); // yes, compiler satisfied.
someX({1,2,3}); //Error. Sorry boss, I don't know the type of array
is there any difference between these two ways ? Are they completely identical in Java ?
No there is no difference. Both of them will create an array of length 3 with the given values.
The 2nd one is just a shorthand of creating an array where you declare it. However, you can't use the 2nd way of creating an array, at any other place than the declaration, where the type of array is inferred from the declared type of array reference.
No, the first and second are the same. The second is just syntactic sugar. Your end result is the same.
int[] myArr = new int[]{1,2,3};
Here it means you are initializing the three variable which will create the length of array 3
int[] myArr = {1,2,3};
Here it means you are initializing the three variable which will by default create the length of array 3
Both ways generate exactly the same result. Both are arrays of length 3 with predefined values. The second one is just shorter. The second method of declaring an array is better if you think that you need less time to write that code.
In the case you need to use that array to directly pass it to a method you should use the first one:
//Correct
someMethod(new int[]{1,2,3});
//Incorrect
someMethod({1,2,3});
But if your goal is only to declare and initialize the array in a variable either ways are correct:
int[] myArr = new int[]{1,2,3}; //Correct
int[] myArr = {1,2,3}; //Also Correct
I am doing one exercise in Absolute Java.
The Question is: Write a static method that has a partially filled array of characters as a formal parameter and that deletes all repeated letters from the array. The method should have two formal parameters: an array parameter and a formal parameter of type int that gives the number of array positions used. When the letter is deleted, the remaining letters are moved one position to fill in the gap.
What I think of is using hashset, it should be the most easiest way.
And another way that I am thinking is converting array to list , deleting the duplicates element and then transfer it back.
Here is a problem for me: how to write that code?? (why I am asking it?)
public static char[] deleteRepeats(char[] array, int size)
{
ArrayList<String> newarray = new ArrayList<String>();
newarray = Arrays.asList(array);
}
it says type mismatching, how can I correct the code?
Another question is: Back to the initial question, how to use partially filled array to implement it?
ArrayList<String> newarray = new ArrayList<String>();
Is an array list of Generic type String. However your parameters are of char type. Therefore they are not interchangeable. That's whats throwing the Type Mismatch error.
You are right using a Set is the easiest way to implement it. However I don't know whether the exercise wants you to manually do the work.
However you if you cannot use the wrapper class Character and must use the char type then you must do manual conversion if you are going to get a Set to do your replacement work for you.
EDIT:
You cannot use Arrays.asList() method to get a list like that. That method takes java objects as arguments not primitive types. And when you pass the char[] the only object it sees is the array itself.
So the result is a List<char[]> since generics do not support primitive types.
I'm using reflection to retrieve an instance field such as this:
private int[] numbers = ....
With the field object, I can check if the field contains an array and if it does, I'd like to loop over the ints in the array. So if the object that contains the above field is called "foo", then I would have something like this:
field.setAccessible(true);
Object value = field.get(foo);
The above value variable will contain my array of ints. How do I treat that object like a regular array and iterate over its values?
Edit: sorry, I missed a crucial point to my story above. I'm doing the above in a generic way so I don't know what primitive the array contains. It could be an int[] or long[] etc. So casting to int[] wouldn't work in the long[] case obviously. oops!
You can use the class java.lang.reflect.Array to access the length and individual elements of an array. The get method should work in a generic way, possibly wrapping primitives in their wrapper objects.
This page has a good treatment under the "Using Arrays" section.
Simplifying (and changing variable names;-) from their array2 example class,
int valuecast[] = (int[])value;
seems to be what you're after.
Edit: the OP now clarifies that he does not know whether the primitive type in the array is int, long, or whatever. I believe the only way to deal with this is an if/else "tree" based on checks on the primitive's type (as in, Integer.TYPE or whatever) -- followed by the appropriate declaration and cast in the conditional's branch that identifies the type in question.
you can cast it to an array like this
int[] a = (int[])value;
Mentioned in Oracles Tutorial this is easily achievable with array.getClass().getComponentType(). This returns the class of the instances in the array.
Afterwards you can check it against the primitive class located inside each wrapper object. For example:
if (array.getClass().getComponentType().equals(Boolean.TYPE)) {
boolean[] booleanArray = (boolean[]) array;
}