private final String[] okFileExtensions = new String[] { "csv" };
Would someone please explain why {} is written after a String array declaration?
Thanks.
It's an array of one element. In this case containing the String "csv".
When written as part of a declaration, this can be written in a more concise form:
private final String[] okFileExtensions = { "csv" };
Multiple-element arrays use commas between values. There needn't be any values at all.
private final String[] okFileExtensions = { "csv", "tsv" };
private final String[] noFileExtensions = { };
It may be worth noting that although the reference is final the array is not. So you can write:
okFileExtensions[0] = "exe";
A way to get around this is to switch to collections and use an unmodifiable implementation:
private final Set<String> okFileExtensions = Collections.unmodifiableSet(
new HashSet<String>(Arrays.asList({
"csv"
}));
JDK8 is intended to have enhancement to collections that will make this more concise. Probably List and Set literals within the language. Possibly:
private final Set<String> okFileExtensions = { "csv" };
Collections should generally be preferred over arrays (for reference types).
That's the Java's valid syntax for array declaration.
You may use that when you are passing an array without declaring a variable:
public void printArray( String [] someArray ) {
for( String s : someArray) {
System.out.println( s );
}
}
And invoke it like this:
printArray( new String [] { "These", "are", "the", "contents"} );
The curly braces can only be used when declaring the array so the following is not allowed:
Stirng [] a;
a = {"on", "two"};
Creating an array of strings inline.
I think a less verbose (also confusing) declaration would have been :
private final String[] okFileExtensions = {"csv"};
Related
When there is a getter method with a return type of String[],
for example:
private static Map<Integer, String[]> map = new HashMap();
public static void setterMethod(int id, String number, String address) {
String[] arr = new String[2];
arr[0] = "number";
arr[1] = "address";
map.put(id, arr);
}
public String[] getterMethod(int id) {
String[] arr = new String[]{map.get(id)[0], map.get(id)[1]};
return arr;
}
When we do a unit test, I need to do something like:
Assert.assertEquals(getterMethod(1), Arrays.asList("number", "Address"));
but this test will fail since getterMethod(1) will print out something like: String#a1b2c223d
How can we make getterMethod() to return in the form of [number, address] whilest maintaining the return type of the getterMethod?
There are two issues here.
First, gettMethod retuns an array of Strings (String[]) and Arrays.asList returns a List<String>, so they will never be equal. Instead of Arrays.asList, you should create an array.
Second, arrays don't overwrite the equals(Object) method, so you need to use a different assertion method that handles arrays:
Assert.assertArraysEquals(getterMethod(1), new String[]{"number", "Address"});
I have an object Keyword that stores a String with the text of the keyword and a set o keywords (Set<Keyword>) that I need to transform into a String array. Is there a quick/easy way to do this or I need to iterate the set and add each keyword one by one?
EDIT:
For those asking for Keyword class:
#Entity
public class Keyword {
// ...
#Basic
private String value;
// ...
// Getters & Setters
}
Every class that implements Collection intefrace (and that includes Set) has toArray() method:
String[] array= set.toArray(new String[0]);
In case of a set that is parametrized with some other type, e.g. Set<Keyword> you would have to do something like:
Keyword[] array= set.toArray(new Keyword[0]);
String[] stringArray= new String[array.length];
for (int i=0; i<array.length; i++) {
stringArray[i]= array[i].getThatString();
}
Try this:
String[] arr = set.toArray(new String[set.size()]);
... is what I would have said, if you had a Set<Object>.
No, there is no way to directly convert a Set<Keyword> to a String[] since there is no direct relationship between Keyword and String. You will have to iterate over the set:
String[] arr = new String[set.size()];
int i = 0;
for (Keyword word : set)
arr[i++] = word.toString();
If you use Guava, you may use this:
Lists.transform(Lists.newArrayList(theSet), Functions.usingToString())
.toArray(new String[theSet.size()])
And this only scratches the surface of what Guava can actually do.
There is no specific way to do this . You can either convert Set to Object[] using set.toArray and then iterate over the array
or
iterate over the set directly
You may need to add toString() method to your Keyword class as shown below. Or you can use a separate transformer class/method.
class Keyword {
private String value;
Keyword(String v) {
this.value = v;
}
public String toString() {
return value;
}
}
.
I would say iterate the set and add each keyword one by one is your best possible strategy.
System.out.println(toStringArray(set));
.
private static String[] toStringArray(Collection<?> set) {
String[] arr = null;
if (set != null) {
arr = new String[set.size()];
int i = 0;
for (Object o : set) {
arr[i++] = o.toString();
}
}
return arr;
}
.
However if you really want, you can have a dirty workaround as shown below. Only issue here is that your keyword value cannot contain comma (,) as it is used by split() method.
String str = set.toString();
str = str.substring(1, str.length() - 1);
String[] asStringArray = str.split(",");
System.out.println(asStringArray);
Let's say I have a String[] that looks like this:
private String[] motherOfStrings = {
"stringA",
"stringB",
"stringC",
"stringD",
"stringE",
}
Can I split it into multiple String[] like these?
private String[] childOfString1 = {
"stringA",
"stringB",
"stringC",
}
private String[] childOfString2 = {
"stringD",
"stringE",
}
Thanks guys :)
p.s., i did some search but most of the guides (if not all) are about splitting String[] into Strings, not another String[]. Is this even possible?
You can use split() method for every string in your array.
String stringByWhichYouWantToSplit = "C";
String[][] splittedStrings = new String[motherOfStrings][];
for(int i = 0; i < motherOfStrings.length; i++)
splittedStrings[i] = motherOfStrings.split(stringByWhichYouWantToSplit);
...if you want to split your strings by "C" ...
EDIT:
Now, when you edited question I see what you want. You have to create two arrays and copy into them strings from motherOfStrings. You can use System.arraycopy method.
Loop through array and split each String into String[] or better maintain a List<String>
Is there a better way of creating arrays from elements of an enum:
public static enum LOGICAL {
AND ("&", "AND"),
OR ("||", "OR");
public final String symbol;
public final String label;
LOGICAL(String symbol, String label) {
this.symbol=symbol;
this.label=label;
}
}
public static final String[] LOGICAL_NAMES = new String[LOGICAL.values().length];
static{
for(int i=0; i<LOGICAL.values().length; i++)
LOGICAL_NAMES[i]=LOGICAL.values()[i].symbol;
}
public static final String[] LOGICAL_LABELS = new String[LOGICAL.values().length];
static{
for(int i=0; i<LOGICAL.values().length; i++)
LOGICAL_LABELS[i]=LOGICAL.values()[i].label;
}
Personally I wouldn't expose them as an array, whose contents can be changed by anyone. I'd probably use an unmodifiable list instead - and probably expose that via a property rather than as a field. The initialization would be something like this:
private static final List<String> labels;
private static final List<String> values;
static
{
List<String> mutableLabels = new ArrayList<String>();
List<String> mutableValues = new ArrayList<String>();
for (LOGICAL x : LOGICAL.values())
{
mutableLabels.add(x.label);
mutableValues.add(x.value);
}
labels = Collections.unmodifiableList(mutableLabels);
values = Collections.unmodifiableList(mutableValues);
}
(If you're already using Guava you might even want to use ImmutableList instead, and expose the collections that way to make it clear that they are immutable.)
No. That seems the proper way. Even if there was some utility, it would rely on reflection
If you are using it often cache it in the enum
If you use your values very frequently and your enumeration gets bigger use Maps. Declare the following in your class.
private static EnumMap<LOGICAL,String> symbols = new EnumMap<LOGICAL, String>(LOGICAL.class);
and then just below it:
static{
for(LOGICAL i : LOGICAL.values().)
symbols.put(i, i.symbol);
}
then you can use symbols.values() or symbols.get(LOGICAL.AND) etc.
I am trying to call this method to concat two arrays using Google Collections
public static <T> T[] concat(T[] first,
T[] second,
Class<T> type)
It's returning empty results. I am using
ObjectArrays.concat(array1, array2, Blah.class)
which is the only thing that compiles.
array1 and array2 are of type Blah[].
What's the right syntax?
Bonus question: do other collections libraries have documentation with examples?
Edit: Problem was my bone-headed code.
public void register(ButtonPair[] pairs) {
pairs = ObjectArrays.concat(this.pairs, pairs, ButtonPair.class);
}
the right side of the thing is okay, but the left side is not assigning to this.pairs due to the ambiguity. Sorry! And hats off to Google Collections!
The following worked for me:
String[] arr1 = { "abc", "def" };
String[] arr2 = { "ghi", "jkl" };
String[] result = ObjectArrays.concat(arr1, arr2, String.class);
How are you getting the result from concat()?
For some example usage of the Google Collections classes, check out the unit tests.
For example:
String[] result = ObjectArrays.concat(
new String[] { "a", "b" }, new String[] { "c", "d" }, String.class);
assertEquals(String[].class, result.getClass());
assertContentsInOrder(Arrays.asList(result), "a", "b", "c", "d");
So, what the Class<T> notation means is that it needs you to specify what class the objects in the other two argument arrays belong to.
Your syntax looks totally correct. I think the problem must be elsewhere. Are you 100% certain about the input values? Here is a test case:
import com.google.common.collect.ObjectArrays;
public class ObjectArrayTest
{
public static void main(String[] args)
{
String[] first = new String[] { "Fire", "Earth" };
String[] second = new String[] { "Water", "Air" };
String[] result = ObjectArrays.concat(first, second, String.class);
for (String s : result)
{
System.out.println (s);
}
}
}
Isn't this because you are not assigning the result to the instance variable but to the method variable.
That is this:
public void register(ButtonPair[] pairs) {
pairs = ObjectArrays.concat(this.pairs, pairs, ButtonPair.class);
}
should be
public void register(ButtonPair[] pairs) {
this.pairs = ObjectArrays.concat(this.pairs, pairs, ButtonPair.class);
}
Incidentally, this is why at our shop we have have a different naming convention for method parameters and variables than that for instance variables (though not the awful prefixing/suffixing of instance variables like _someInstanceVar).