Passing elipses as an argument to java method - java

I have a Java method which accepts arguments in ellipses format. This method in turns call an api which again accepts parameters in ellipses format:
public void myMethod(String a, String... listOfParam){
//Method Signature of anotherAPI is anotherAPI(String input, Object ... listOfParams)
//I call anotherAPI method as described below.
String result = anotherAPI(a, listOfParam);
}
However, when I pass listOfParams as arguments, I get UnsupportedOperationException.
Please let me know the correct approach in this case.
Edit
I am calling AmazonDynamoDB Java API's
(http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html?index-all.html) addHashOnlyPrimaryKeys method :
The client method is as below :
public static List<Item> getAllItems(String tableName,String primaryKeyName, String ... listOfKeys){
List<Item> itemList = null;
System.out.println(listOfKeys.toString());
TableKeysAndAttributes tkaa = new TableKeysAndAttributes(tableName);
tkaa.addHashOnlyPrimaryKey(primaryKeyName, listOfKeys);
BatchGetItemOutcome outcome = dynamoDB.batchGetItem(tkaa);
itemList = outcome.getTableItems().get(tableName);
return itemList;
}
I testing this method as :
List<Item> listOfItems = AmazonDynamoDBUtil.getAllItems("myTable","data","1","2","3","4");
Here is data is of type String.
However, the exception which I am getting is :
Exception in thread "main" java.lang.UnsupportedOperationException: value type: class [Ljava.lang.String;
at com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.toAttributeValue(InternalUtils.java:221)
at com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.toAttributeValueMap(InternalUtils.java:535)
at com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.toAttributeValueMap(InternalUtils.java:547)
at com.amazonaws.services.dynamodbv2.document.internal.BatchGetItemImpl.doBatchGetItem(BatchGetItemImpl.java:84)
at com.amazonaws.services.dynamodbv2.document.internal.BatchGetItemImpl.batchGetItem(BatchGetItemImpl.java:58)
at com.amazonaws.services.dynamodbv2.document.DynamoDB.batchGetItem(DynamoDB.java:154)
at awsdynamodb.AmazonDynamoDBUtil.getAllItems(AmazonDynamoDBUtil.java:63)
Please let me know what can be wrong with this approach.

This is working:
public class Main {
public static void main(String[] args) {
myMethod("test 1");
myMethod("test 2", "a");
myMethod("test 3", "a", "b", "c");
}
public static void myMethod(String a, String... listOfParam) {
anotherAPI(a, listOfParam);
}
private static void anotherAPI(String a, String... listOfParam) {
StringBuilder sb = new StringBuilder();
for (String p : listOfParam) {
sb.append(p);
sb.append(", ");
}
System.out.println(a + ": " + sb.toString());
}
}
produces the expected result:
test 1:
test 2: a,
test 3: a, b, c,
From a Java point of view listOfParam as String... is a String[] array.

The following code runs fine for me, albeit with a warning (which you can get rid of by casting the second parameter of the call to anotherAPI() to Object[]):
public class Test
{
public static String anotherAPI(final String a, final Object... listOfParam)
{
for (final Object param : listOfParam)
System.out.println(param);
return "Test";
}
public static void main(final String[] args)
{
myMethod("a", "This", "is", "a", "test");
}
public static void myMethod(final String a, final String... listOfParam)
{
final String result = anotherAPI(a, listOfParam);
System.out.println(result);
}
}
with the output:
This
is
a
test
Test
I think the implementation of anotherAPI() doesn't allow for what you are trying to do.

The API doesn't support that method call (hence the unsupported exception). Nothing to do with ellipsis. Don't call that method, it won't work.

Sorry guys , it seems I was calling addHashOnlyPrimaryKey instead of addHashOnlyPrimaryKeys :)

Related

Method containing interface as parameter

hello how do I call a method taking an interface as a parameter from the main ?
The code in the main is an example of what I want to achieve but by calling the method map now
What do I write in my map method and how do I call it in the main ? Thank you
What I want to achieve :
StringTransformation addBlah = (e) -> {
e += "boo";
return e;
};
System.out.println(addBlah.transf("Hello")); // prints Helloboo
public class Main{
public static void main(String[] args) {
String a = hello;
// How do I modify the string a by calling map ?
}
void map(StringTransformation t) {
// What do I write ??
}
}
public interface StringTransformation {
String transf(String s);
}
You want to modify a String with a given StringTransformation so you need to pass both of them to the map method. Also you can turn addBlah in a more simple lambda :
public static void main(String[] args) {
StringTransformation addBlah = (e) -> e + "boo";
String str = "Hello";
System.out.println(str); // Hello
str = map(addBlah, str);
System.out.println(str); // Helloboo
}
static String map(StringTransformation t, String argument) {
return t.transf(argument);
}
You cannot call map inside the static main method. You must make map a static method as well if you want to do that. Also we can't help you with what to put inside your map function if you don't tell us what it should do.
public static void main(String[] args) {
String string = "Hello";
// you can call `mapBoo` like normal here
string = mapBoo(string);
System.out.println(string);
List<String> strings = Arrays.asList("Hello", "this", "is", "a", "test");
// or you can pass mapBoo into the stream.map method since map fits the method signature
List<String> mappedStrings = strings.stream().map(Main::mapBoo)
.collect(Collectors.toList());
for (String mappedString : mappedStrings)
System.out.println(mappedString);
}
static String mapBoo(String s) {
return s + "boo";
}

Function chaining in Java

I need to do a lot of different preprocessing of some text data, the preprocessing consists of several simple regex functions all written in class Filters that all take in a String and returns the formatted String. Up until now, in the different classes that needed some preprocessing, I created a new function where I had a bunch of calls to Filters, they would look something like this:
private static String filter(String text) {
text = Filters.removeURL(text);
text = Filters.removeEmoticons(text);
text = Filters.removeRepeatedWhitespace(text);
....
return text;
}
Since this is very repetitive (I would call about 90% same functions, but 2-3 would be different for each class), I wonder if there are some better ways of doing this, in Python you can for example put function in a list and iterate over that, calling each function, I realize this is not possible in Java, so what is the best way of doing this in Java?
I was thinking of maybe defining an enum with a value for each function and then call a main function in Filters with array of enums with the functions I want to run, something like this:
enum Filter {
REMOVE_URL, REMOVE_EMOTICONS, REMOVE_REPEATED_WHITESPACE
}
public static String filter(String text, Filter... filters) {
for(Filter filter: filters) {
switch (filter) {
case REMOVE_URL:
text = removeURL(text);
break;
case REMOVE_EMOTICONS:
text = removeEmoticons(text);
break;
}
}
return text;
}
And then instead of defining functions like shown at the top, I could instead simply call:
filter("some text", Filter.REMOVE_URL, Filter.REMOVE_EMOTICONS, Filter.REMOVE_REPEATED_WHITESPACE);
Are there any better ways to go about this?
Given that you already implemented your Filters utility class you can easily define a list of filter functions
List<Function<String,String>> filterList = new ArrayList<>();
filterList.add(Filters::removeUrl);
filterList.add(Filters::removeRepeatedWhitespace);
...
and then evaluate:
String text = ...
for (Function<String,String> f : filterList)
text = f.apply(text);
A variation of this, even easier to handle:
Define
public static String filter(String text, Function<String,String>... filters)
{
for (Function<String,String> f : filters)
text = f.apply(text);
return text;
}
and then use
String text = ...
text = filter(text, Filters::removeUrl, Filters::removeRepeatedWhitespace);
You could do this in Java 8 pretty easily as #tobias_k said, but even without that you could do something like this:
public class FunctionExample {
public interface FilterFunction {
String apply(String text);
}
public static class RemoveSpaces implements FilterFunction {
public String apply(String text) {
return text.replaceAll("\\s+", "");
}
}
public static class LowerCase implements FilterFunction {
public String apply(String text) {
return text.toLowerCase();
}
}
static String filter(String text, FilterFunction...filters) {
for (FilterFunction fn : filters) {
text = fn.apply(text);
}
return text;
}
static FilterFunction LOWERCASE_FILTER = new LowerCase();
static FilterFunction REMOVE_SPACES_FILTER = new RemoveSpaces();
public static void main(String[] args) {
String s = "Some Text";
System.out.println(filter(s, LOWERCASE_FILTER, REMOVE_SPACES_FILTER));
}
}
Another way would be to add a method to your enum Filter and implement that method for each of the enum literals. This will also work with earlier versions of Java. This is closest to your current code, and has the effect that you have a defined number of possible filters.
enum Filter {
TRIM {
public String apply(String s) {
return s.trim();
}
},
UPPERCASE {
public String apply(String s) {
return s.toUpperCase();
}
};
public abstract String apply(String s);
}
public static String applyAll(String s, Filter... filters) {
for (Filter f : filters) {
s = f.apply(s);
}
return s;
}
public static void main(String[] args) {
String s = " Hello World ";
System.out.println(applyAll(s, Filter.TRIM, Filter.UPPERCASE));
}
However, if you are using Java 8 you can make your code much more flexible by just using a list of Function<String, String> instead. If you don't like writing Function<String, String> all the time, you could also define your own interface, extending it:
interface Filter extends Function<String, String> {}
You can then define those functions in different ways: With method references, single- and multi-line lambda expressions, anonymous classes, or construct them from other functions:
Filter TRIM = String::trim; // method reference
Filter UPPERCASE = s -> s.toUpperCase(); // one-line lambda
Filter DO_STUFF = (String s) -> { // multi-line lambda
// do more complex stuff
return s + s;
};
Filter MORE_STUFF = new Filter() { // anonymous inner class
// in case you need internal state
public String apply(String s) {
// even more complex calculations
return s.replace("foo", "bar");
};
};
Function<String, String> TRIM_UPPER = TRIM.andThen(UPPERCASE); // chain functions
You can then pass those to the applyAll function just as the enums and apply them one after the other in a loop.

Generic Singleton Factory

While reading online, I came across the following:
public interface UnaryFunction<T>
{
T apply(T arg);
}
.......
private static UnaryFuntion<Object> ID_FUNC = new UnaryFunction<Object>
{
Object apply(Object arg)
{
return arg;
}
};
public static <T> UnaryFunction<T> idFunction()
{
return (UnaryFunction<T>) ID_FUNC;
}
In main:
public static void main(String[] args)
{
String[] strings = {"Peter", "Paul", "Mary"};
UnaryFunction<String> names = idFunction();
for(String s : strings)
{
System.out.println(names.apply(s));
}
Number[] numbers = {1, 2.0, 3L};
UnaryFunction<Number> nums = idFunction();
for(Number n : numbers)
{
System.out.println(nums.apply(n));
}
}
My question is, why do we need a generic interface here?
Would simply the following suffice:
public interface UnaryFunction
{
Object apply(Object arg); //Object as return type and argument type, instead.
}
? What is the need here to use generics?
And, what is actually a generic singleton factory? What is it good for?
Thanks.
The generic singleton factory is the idFunction in your example. Without it you would have a choice between two ugly alternatives, either require a cast wherever you use it, like this:
public class ExampleWithoutGenericSingletonFactory {
static UnaryFunction<Object> ID_FUNC = new UnaryFunction<Object>() {
public Object apply(Object arg) {
return arg;
}
};
public static void main(String[] args) {
BigDecimal b = new BigDecimal("1234.1241234");
BigDecimal b1 = (BigDecimal)(ID_FUNC.apply(b)); // have to cast here >_<
System.out.println("engineeringstring val of b1 = "
+ b1.toEngineeringString());
}
}
or make separate implementations for every type you want to support:
public static UnaryFunction<String> ID_FUNC_STRING = new UnaryFunction<String>() {
public String apply(String arg) {
return arg;
}
};
public static UnaryFunction<Number> ID_FUNC_NUM = new UnaryFunction<Number>() {
public Number apply(Number arg) {
return arg;
}
};
public static UnaryFunction<BigDecimal> ID_FUNC_DECIMAL = new UnaryFunction<BigDecimal>() {
public Number apply(BigDecimal arg) {
return arg;
}
};
giving you some ugly verbose cut-n-pasted code with a different name for every type that you have to keep straight. But since you know it's a pure function and the types get erased, you can have only one implementation (ID_FUNC) and have the singleton factory idFunction return it.
You would use this for cases where you have one function implementation that you want to be able to specify different types on, where the implementation is stateless.
The example could be better, since it only calls toString on the objects returned from the function call there's no demonstrated benefit from the factory. If the example showed using type-specific methods on the objects returned then the benefit might be more apparent.
An unchecked cast warning comes up when you do this, but it's safe to suppress it (which is what Joshua Bloch advises).

How do I use getConstructor(params).newInstance(args)?

This could well be a stupid question, but I'm new to Java, so...
I've currently got some code where currently this is being used
clazz.asSubclass(asSubclassOfClass).getConstructor().newInstance()
I need to pass some arguments to the contructort so I want to change it to: clazz.asSubclass(asSubclassOfClass).getConstructor(params).newInstance(args)
What I don't understand is what I need to pass in as params and what I need to pass in as args.
Let's say I wanted to pass in a String "howdy" and some object of type XYZ called XyzObj in. How would I specify that? WHat would I pass as params and what would I pass as args?
In Java this is called Reflection.
Assuming the class has this constructor, otherwise you will get a NoSuchMethod exception I believe.
clazz.asSubclass(asSubclassOfClass)
.getConstructor(String.class,XYZ.class)
.newInstance("howdy",XyzObj);
Since you are new to Java, let me give you an easier so that you can understand what's going on under the hood when you do this.
Assume you have the following class:
public class ParentClazz{
String someVar;
public ParentClazz(){
someVar="test";
}
public ParentClazz(String someVar){
System.out.println("I have been invoked");
this.someVar=someVar;
}
}
Then you have the following main method:
public static void main(String[] args) throws ParseException, IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
ParentClazz.class.asSubclass(ParentClazz.class).getConstructor(String.class).newInstance("howdy");
}
If you run this you will notice the console output print message - I have been invoked. This means that using reflection you have invoked the constructor of ParentClazz.
You can do the same thing if the scenario allows you is by using standard object creation process:
ParentClazz clazz = new ParentClazz("howdy");
Hope this helps you understand it.
Here is an example of creating classes without the new keyword.
The classes take other classes both primitives and Objects as their parameters.
The example also shows the instance of a subclass and a Parent class being created
public class ConstructorInstantiateWithoutNew
{
#SuppressWarnings("rawtypes")
public static void main( String [] args )
{
Class<Drinker> clazz_drinker = Drinker.class;
Class [] paramTypes = { Fizz.class, Colour.class, int.class };
Object [] paramValues = { new Fizz(), new Colour(), new Integer(10) };
Class<Drunk> clazz_drunk = Drunk.class;
Class [] paramTypesSub = { Fizz.class, Colour.class, int.class, boolean.class };
Object [] paramValuesSub = { new Fizz(), new Colour(), new Integer(10), true };
try
{
Drinker drinker = clazz_drinker.getConstructor( paramTypes ).newInstance( paramValues );
drinker.drink();
Drunk drunk = clazz_drunk.getConstructor(paramTypesSub).newInstance(paramValuesSub);
drunk.drink();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class Drinker
{
int n;
public Drinker( Fizz f, Colour c, int n)
{
this.n = n;
}
public void drink()
{
System.out.println( "Dad drank " + (n*10) + " ml");
}
}
class Drunk extends Drinker
{
boolean trouble;
public Drunk(Fizz f, Colour c, int n, boolean inDogHouse)
{
super(f,c,n);
trouble = inDogHouse;
}
public void drink()
{
System.out.println(
"Dad is Grounded: " + trouble +
" as he drank over "+
(n*10) + " ml");
}
}
class Fizz {} class Colour {}
Hope this is useful
Kind regards
Naresh Maharaj
clazz.asSubclass(asSubclassOfClass)
.getConstructor(String.class, XYZ.class)
.newInstance("howdy", XyzObj)
Which assumes that the constructor args are in the specified order

Java constructor varargs conflict when passing string

I have an issue with one of my class. I'm using a "varargs" constructor for unknown number of parameter.
public Groupe(String...nom){
for(String item:nom){
this.nom.add(item.toLowerCase());
}
}
public Groupe(String nom){
String[] list =nom.split(",");
for(String s : list){
this.nom.add(s.toLowerCase());
}
}
The first constructor is called...that's fine, but there is a conflict when passing only ONE parameter with the second contructor. I would like to use the second constructor when passing only one string, and the first if 2 and more parameters.
I'd want to handle this
new Groupe("Foo,Bar");
This is where I call it. I suspect the "error" comes from there
public void reserver(String...nom){
Groupe gr = new Groupe(nom);
passager.add(gr);
}
I don't pass a String, but a Varargs (tab?)...
It should be fine, with the caveat that null can be converted to either String[] or String:
public class Test {
public Test(String single) {
System.out.println("Single");
}
public Test(String... multiple) {
System.out.println("Multiple");
}
public static void main(String[] args) {
new Test("Foo"); // Single
new Test("Foo", "Bar"); // Multiple
new Test(); // Effectively multiple
// new Test(null); // Doesn't compile - ambiguous
new Test((String) null); // Single
}
}
EDIT: Now that you've shown us the calling code, that's definitely the problem:
public void reserver(String...nom){
Groupe gr = new Groupe(nom);
passager.add(gr);
}
Here, the type of nom is String[] - so it will always call the first constructor. You've got an array of strings there - under what circumstances do you want to call the second constructor?
To be honest, given that the two constructors act significantly differently, I would actually make both constructors private, and provide static methods:
public static Groupe fromStringArray(String... nom)
public static Groupe fromCommaSeparatedString(String nom)
Then it will be absolutely clear what you're expecting in each case.
Maybe this can be a solution:
public Groupe(String...nom){
if (nom.length == 1) {
add(nom[0].split(","));
} else {
add(nom);
}
}
private void add(String[] list) {
for(String s : list){
this.nom.add(s.toLowerCase());
}
}
The varargs part can be empty. So you can get what you want with
public Groupe(String nom){
String[] list = nom.split(",");
for(String s : list){
this.nom.add(s.toLowerCase());
}
public Groupe(String nom1, String nom2, String...nom){
this.nom.add(nom1);
this.nom.add(nom2);
for(String item:nom)
this.nom.add(item.toLowerCase());
}
You could also, of course, use one ctor with an if statement on the length of the input array, splitting out cases 0 (not handled with the code above), 1, and > 1.
public class OverloadVarArgs {
public static void main(String... args){
OverloadVarArgs a = new OverloadVarArgs("One Argument");
OverloadVarArgs b = new OverloadVarArgs("Two", "Arguments");
OverloadVarArgs c = new OverloadVarArgs("One, Argument");
}
public OverloadVarArgs(String a){
System.out.println("Constructor 1");
}
public OverloadVarArgs(String... a){
System.out.println("Constructor 2");
}
}
Output:
Constructor 1
Constructor 2
Constructor 1

Categories

Resources