Hot questions for Operating Array in Guava

Top 10 Java Open Source / Guava / Operating Array

Lists.newArrayList vs new ArrayList

Question: What is the best construction for creating a List of Strings? Is it Lists.newArrayList() (from guava) or new ArrayList()?

is it just a personal preference?

or is it just Type generic type inference?

or is there any theoretical or practical value in using Lists.newArrayList()?

Answer: The guava builder saves typing the type arguments multiple times. Compare:

List<Foo<Bar, Baz>> list = Lists.newArrayList();
List<Foo<Bar, Baz>> list = new ArrayList<Foo<Bar, Baz>>();

In Java it's a bit obsolete though, because you have the diamond operator:

ist<Foo<Bar, Baz>> list = new ArrayList<>();

Is there a way to find common elements in multiple lists?

Question: I have a list of integer arrays. I need to find the common elements between those.

Example would be 
[1,3,5],
[1,6,7,9,3],
[1,3,10,11]

should result in [1,3]

There are no duplicates in the arrays as well.

Is there a straight forward way to do this?

Answer: You can transform the lists to sets, and use Set's intersection method offered by Guava, Here is a little example:

public <T> Set<T> intersection(List<T>... list) {
    Set<T> result = Sets.newHashSet(list[0]);
    for (List<T> numbers : list) {
        result = Sets.intersection(result, Sets.newHashSet(numbers));
    }
    return result;
}

Transform a Generic Array Efficiently Using Guava

Question: I'm searching in the Guava API for a way to apply a function to an array without having to convert it to a Collection first.

So as a summary (in case you don't know exactly what I'm talking about), this is what I've found so far that you can do with Guava in order to apply a function to an array as I said:

Integer[] someNumbers = new Integer[]{1, 2, 3};
Integer[] returnedNumbers = Collections2.transform(Arrays.asList(someNumbers), squareNumberFunction).toArray(new Integer[0]);

assertThat(returnedNumbers).isEqualTo(new Integer[]{1, 4, 9});//Using AssertJ here

But I would like to be able to do something like this instead:

Integer[] someNumbers = new Integer[]{1, 2, 3};
Integer[] returnedNumbers = Arrays.transform(someNumbers, squareNumberFunction);

assertThat(returnedNumbers).isEqualTo(new Integer[]{1, 4, 9});

Ideally the functionality I'm talking about would be type-safe.

Answer: Maybe you can try:

public static <A, B> B[] transform(Class<B> theReturnedValueType, Function<A, B> functionToApply, A... theValues) {

    B[] transformedValues = (B[]) Array.newInstance(theReturnedValueType, theValues.length);

    for (int i = 0; i < theValues.length; i++) {
        transformedValues[i] = functionToApply.apply(theValues[i]);
    }

    return transformedValues;
}

Example of how to use it (actually this is a test):

Integer[] returnedNumbers = ArrayTransformer.transform(Integer.class, squareNumberFunction, 1, 2, 3);

assertThat(returnedNumbers).isEqualTo(new Integer[]{1, 4, 9});

I want to point out that the example code is using vargargs syntax (it's a test, so it's a fun way to use it) but you can just obviously passed an array object instead.

Also, I must add that you need to be careful with this approach when using it on an environment sensitive to reflection performance hits (such as Android), because of the runtime creation of the new array using reflection (java.lang.reflect.newInstance(...)). In the other hand, the same holds true if you are using toArray(T[]) method of collections and the passed array's size isn't enough to hold all the collection elements (in which case a new array is allocated at run time, just as with my code), so maybe this code doesn't represent a problem if anyway you are using that method in the way I said (in any case you could easily change this code to fit your needs).


filtering an ArrayList using an object's field

Question: I have an ArrayList which is filled by Objects.

My object class called Article which has two fields;

public class Article {

    private int codeArt;
    private String desArt;

  public Article(int aInt, String string) {
        this.desArt = string;
        this.codeArt = aInt;
    }

    public int getCodeArt() {return codeArt; }
    public void setCodeArt(int codeArt) {this.codeArt = codeArt;}
    public String getDesArt() {return desArt;}
    public void setDesArt(String desArt) { this.desArt = desArt;}
}

I want to filter my List using the desArt field, and for test I used the String "test".

I used the Guava from google which allows me to filter an ArrayList.

this is the code I tried :

private List<gestionstock.Article> listArticles = new ArrayList<>();

//Here the I've filled my ArrayList

private List<gestionstock.Article> filteredList filteredList = Lists.newArrayList(Collections2.filter(listArticles, Predicates.containsPattern("test")));

but this code isn't working.

Answer: This is normal: Predicates.containsPattern() operates on CharSequence, which your gestionStock.Article object does not implement.

You need to write your own predicate:

public final class ArticleFilter
    implements Predicate<gestionstock.Article>
{
    private final Pattern pattern;

    public ArticleFilter(final String regex)
    {
        pattern = Pattern.compile(regex);
    }

    @Override
    public boolean apply(final gestionstock.Article input)
    {
        return pattern.matcher(input.getDesArt()).find();
    }
}

Then use:

private List<gestionstock.Article> filteredList
     = Lists.newArrayList(Collections2.filter(listArticles,     
         new ArticleFilter("test")));

Java - Append quotes to strings in an array and join strings in an array

Question: I would like to append double quotes to strings in an array and then later join them as a single string (retaining the quotes). Is there any String library which does this? I have tried Apache commons StringUtils.join and the Joiner class in Google guava but couldn't find anything that appends double quotes.

My input would be an array as mentioned below:

String [] listOfStrings = {"day", "campaign", "imps", "conversions"};

Required output should be as mentioned below:

String output = "\"day\", \"campaign\", \"imps\", \"conversions\"";

I know I can loop through the array and append quotes. But I would like a more cleaner solution if there is one.

Answer:

1. With Java 8+

Java 8 has Collectors.joining() and its overloads. It also has String.join.

Using a Stream and a Collector

Function<String,String> addQuotes = s -> "\"" + s + "\"";

String result = listOfStrings.stream()
  .map(addQuotes)
  .collect(Collectors.joining(", "));

Using String.join

String result = listOfString.isEmpty() ? "" : "\"" + String.join("\", \"", listOfStrings) + "\"";

2. Using Guava

Function<String,String> addQuotes = new Function<String,String>() {
  @Override public String apply(String s) {
    return new StringBuilder(s.length()+2).append('"').append(s).append('"').toString();
  }
};
String result = Joiner.on(", ").join(Iterables.transform(listOfStrings, addQuotes));

3. No libraries

String result;
if (listOfStrings.isEmpty()) {
  result = "";
} else {
  StringBuilder sb = new StringBuilder();
  Iterator<String> it = listOfStrings.iterator();
  sb.append('"').append(it.next()).append('"'); // Not empty
  while (it.hasNext()) {
    sb.append(", \"").append(it.next()).append('"');
  }
  result = sb.toString();
}

Note: all the solutions assume that listOfStrings is a List<String> rather than a String[]. You can convert a String[] into a List<String> using Arrays.asList(arrayOfStrings). You can get a Stream<String> directly from a String[] using Arrays.stream(arrayOfString).