C# lets me make arrays on the fly when I need to pass them into functions. Let's say I have a method called findMiddleItem(String[] items). In C#, I can write code like:
findMiddleItem(new String[] { "one", "two", "three" });
It's awesome, because it means I don't have to write:
IList<String> strings = new List<String>();
strings.add("one");
strings.add("two");
strings.add("three");
findMiddleItem(strings.ToArray());
Which sucks, because I don't really care about strings -- it's just a construct to let me pass a string array into a method that requires it. A method which I can't modify.
So how do you do this in Java? I need to know this for array types (eg. String[]) but also generic types (eg. List).
A List and an Array are fundamentally different things.
A List is a Collection type, an implementation of an interface.
An Array is a special operating system specific data structure that can only be created through either a special syntax or native code.
Arrays
In Java, the array syntax is identical to the one you are describing:
String[] array = new String[] { "one", "two", "three" };
Reference: Java tutorial > Arrays
Lists
The easiest way to create a List is this:
List<String> list = Arrays.asList("one", "two", "three");
However, the resulting list will be immutable (or at least it won't support add() or remove()), so you can wrap the call with an ArrayList constructor call:
new ArrayList<String>(Arrays.asList("one", "two", "three"));
As Jon Skeet says, it's prettier with Guava, there you can do:
Lists.newArrayList("one", "two", "three");
Reference: Java Tutorial > The List Interface, Lists (guava javadocs)
VarArgs
About this comment:
It would be nice if we would be able to do findMiddleItem({ "one", "two", "three" });
Java varargs gives you an even better deal:
public void findMiddleItem(String ... args){
//
}
you can call this using a variable number of arguments:
findMiddleItem("one");
findMiddleItem("one", "two");
findMiddleItem("one", "two", "three");
Or with an array:
findMiddleItem(new String[]{"one", "two", "three"});
Reference: Java Tutorial > Arbitrary Number of Arguments
In Java you can construct an array in the same way:
findMiddleItem(new String[] { "one", "two", "three" });
You can't construct a List<T> in quite the same way, but there are various ways of getting around that, e.g. wrapping an array, or using some of the Guava Lists.* methods. (Your code trying to call findMiddleItem with an argument of type IList<string> wouldn't have compiled, as an IList<string> isn't necessarily a string[].) For example, if findMiddleItem actually had a parameter of type List<String> you could use:
findMiddleItem(Lists.newArrayList("one", "two", "three"));
As well as not having collection initializers (or object initializers), Java also doesn't have implicitly typed arrays... your original C# code can be condensed in C# 3 and higher:
findMiddleItem(new[] { "one", "two", "three" });
You can do it the exact same way:
findMiddleItem(new String[] { "one", "two", "three" });
is valid in Java. Assuming that findMiddleItem is defined as:
findMiddleItem(String[] array)
The same way as in C# findMiddleItem(new String[] { "one", "two", "three" });
Also, for future reference, you can construct a List in Java in a slightly less-verbose way*:
List<String> myStringList = new ArrayList<String>() {{
add("a");
add("b");
add("c");
}};
* As Sean pointed out, this can be considered bad practice since it does create an anonymous subclass of ArrayList.
I think it's the exact same syntax in Java. This works:
public class Main
{
public static void main( String[] args )
{
method1( new String[] {"this", "is", "a", "test"} );
}
private static void method1( String[] params )
{
for( String string : params )
System.out.println( string );
}
}
I think this will work on non-static methods, too.
Apart from using vargs like
findMiddleItem("one", "two", "three", "four", "five");
you can do
findMiddleItem("one,two,three,four,five".split(","));
EDIT: to turn a String into a List you can use a helper method.
public static List<String> list(String text) {
return Arrays.asList(text.split(","));
}
findMiddleItem(list("one,two,three,four,five"));
Related
I've seen All possible C# array initialization syntaxes which shows several different ways to initialize an array.
Does the following initialization creates an instance that is different in some ways compared to one created with regular call with new ?
Initialization:
string[] strArray = {"one","two","three"};
Compared to string[] strArray = new String[] {"one","two","three"};
It is a syntactic sugar. The compiler transforms this:
string[] strArray = {"one","two","three"};
To This:
string[] expr_07 = new string[] {
"one",
"two",
"three"
};
Above output is using Roslyn C# compiler.
You can't initialize something that's not there. So yes, a new instance does get created, in the exact same way as though you had written the new operator. It's just a convenience provided by the language for when you're initializing an array at the same time that you're declaring it so you aren't forced to write it out (when doing it in a separate statement, the new operator is required because the compiler can't assume you haven't already assigned an array reference to the variable beforehand — the very bare minimum you can get away with in a separate statement is strArray = new[] {...};).
I'm studying a book with Membership topic in ASP.NET MVC and I found syntax, I cannot trace (and not explained in the book), which is:
new[] {"string"}
like in:
Roles.AddUsersToRoles(new[] {userName}, new[] {roleName});
Per MDSN library I see Roles.AddUsersToRoles method takes two string arrays as arguments, so likely this is a shorthand or would this have some additional functionality?
It is Implicitly Typed Arrays syntax.
You can create an implicitly-typed array in which the type of the
array instance is inferred from the elements specified in the array
initializer.
This
string[] stringArray = new[] {"string"};
is same as :
string[] stringArray = new string[] {"string"};
Other thing to note, the method Roles.AddUsersToRoles accepts two parameters of string type array (and not a string).
public static void AddUsersToRoles(
string[] usernames,
string[] roleNames
)
new string[1] { "string" }
You can omit the array size because the compiler can count the number of elements for you:
new string[ ] { "string" }
You can also omit the array element type because the compiler can infer it from the values provided:
new [ ] { "string" }
But do not get this mixed up with initializers for anonymous types. These do not have the angle brackets [] after new:
new { StringProperty = "string" }
or:
// string StringProperty;
new { StringProperty }
Having the code below, why is the variable declaration considered as correct syntax, but not also the method call?
public static void Func(string[] p)
{
}
public static void Test()
{
string[] a = { "x", "y", "z" };
Func({"x", "y", "z"});
}
It looks like everybody else is focusing on the workaround (which is simply to specify that you need a new [] { "some", "strings" }. The why is a little less obvious though.
The former is valid because the compiler knows to use your initialization syntax to create an Array (because you've defined it as such).
The later would have some issues. It may seem trivial in this case because the compiler should, theoretically, be able to figure out that you need a string[]. Think about cases where you have a Func<IEnumerable<string>> though. What type gets generated in that case? Would the compiler take a wild-ass guess? Always use an Array (even though there might be a better fit)? It could be one of a number of possibilities.
I'm guessing that's the reason that the language specification doesn't allow for passing things this way.
You need to pass in a value as the argument. {"x", "y", "z"} is not a value. It can be used as short-hand for initializing a variable.
Note that both of these are valid:
List<string> a = new List<string>() {"x", "y", "z"};
string[] b = new string[] {"x", "y", "z"};
And the full version of what it represents:
List<string> a = new List<string>();
a.Add("x");
a.Add("y");
a.Add("z");
So you need to make an object (new)
new [] {"x", "y", "z"}
Or make an object beforehand and pass that in.
As for why this is like this, you need to pass in a value, not a helper for array initialization.
You can initialize the object directly on the inside of the method call, but do not think a good practice.
where you used:
Func ({"x", "y", "z"});
The above form you tried to pass an object not instantiated, ie it does not already exist on your "context". The correct is you initialize it to be generated in a reference memory to this value and thus the "Func" method you can use it.
In the case of variable declaration:
string[] a = {"x", "y", "z"};
In this case your compiler is reading:
string[] a = new string[] {"x", "y", "z"};
It does this interpretation alone, without requiring you to do object initialization explicitly.
So my answer is best for this situation you must first create the object then pass it as a parameter to the method:
string[] a = {"x", "y", "z"};
Func (s);
I have two lists of strings both of which are ~300,000 lines. List 1 has a few lines more than List 2. What I'm trying to do is find the strings that in List 1 but not in List 2.
Considering how many strings I have to compare, is Except() good enough or is there something better (faster)?
Internally the enumerable Except extension method uses Set<T> to perform the computation. It's going to be as least as fast as any other method.
Go with list1.Except(list2).
It'll give you the best performance and the simplest code.
My suggestion:
HashSet<String> hash1 = new HashSet<String>(new string[] { "a", "b", "c", "d" });
HashSet<String> hash2 = new HashSet<String>(new string[] { "a", "b" });
List<String> result = hash1.Except(hash2).ToList();
var movieNext = new string[,]
{
{ "superhero", "action", "waltdisney", "bat"},
{"superhero", "action", "marvel",""},
{"history", "action", "malay", "" },
{"malay", "novel", "", ""},
{"history", "bat", "", ""}
};
The above code is a multidimensional array, which stores a sequence of movie's keyword. Is there a way to implement this without having to put the blank strings in the array initialization?
For example you can see in the above code, I have to put the blank string "" to fill up the array.
You could use a jagged array instead.
string[][] movieNext = new string[][] { { etc... } }.
You can consider C# jagged array (though they are different from multi-dimensional arrays).
string[][] movieNext = {
new [] { "superhero", "action", "waltdisney", "bat"},
new [] {"superhero", "action", "marvel"}, <and so on>
};
If you want to stick with multi-dimensional arrays, you have to initialize the values individually. If you don't provide any string value for any of the index (i,j) by default it will be null.
I suggest never to use two-dimensional arrays. They have practically no support in the API (you'll be hard pressed to find a method that accepts a two-dimensional array as a parameter), and cannot be cast to IEnumerable<T> or similar well-supported interface. As such, you can really use them only in the most local of scopes.
Instead, I suggest you use something castable to IEnumerable<IEnumerable<string>>. Oh, another tip. Check this out. Specifically,
To initialize a Dictionary, or any collection whose Add method takes multiple parameters, enclose each set of parameters in braces as shown in the following example.
Thus, the following will work:
class Program
{
static void Main(string[] args)
{
var d = new ManyList()
{
{"Hi", "Good", "People", "None", "Other"}
{"Maybe", "Someone", "Else", "Whatever"}
};
Console.Read();
}
}
class ManyList : List<string>
{
public void Add(params string[] strs)
{
Console.WriteLine(string.Join(", ", strs));
}
}
This might help you clean up your syntax a bit.