1

I understand now how to create limitless arguments as per Java method with unlimited arguments

But I was wondering what is the syntax to extend this to two arguments, akin to printf?

I want to create unlimited String, int pairs.

The goal would be to display String1 : Int1, String2: Int2 and so on. I'm just not sure what the syntax would be, let alone if it's possible.

Community
  • 1
  • 1
Legato
  • 609
  • 17
  • 24

4 Answers4

2

Well, firstly, you can't do this:

public void foo(String... strings, int... ints) {

Since you'll get an error that the varargs parameter strings needs to be the last one.

So you'll likely want to make a small wrapper class, say StringWithInt and then do like so:

public void foo(StringWithInt... values) {

I hope this helps!

vikingsteve
  • 38,481
  • 23
  • 112
  • 156
  • 1
    The invocation of `foo` becomes quite bulky, though: `foo(new StringWithInt("hello", 1), new StringWithInt("world", 2), new StringWithInt("!", 3))`. To me, this is a rather heavy price to pay for static type safety. Of course, others may hold a different opinion on this. – Sergey Kalinichenko Jun 23 '14 at 20:12
2

It's not directly possible but here are some approaches:

  1. If the strings will be unique, you can pass the data as a Map:

    public void method(Map<String,Integer> pairs) {
        ...
    }
    
  2. You can use two separate arrays:

    public void method(String[] strings, int[] ints) {
        if (strings.length != ints.length) throw new IllegalArgumentException();
        ...
    }
    

    Call as:

    method(new String[] { "a", "b", "c" }, new int[] { 1, 2, 3 });
    
  3. Use Object for everything and sort it out later. This suffers from ugly internals and a lack of compile-time type checking but it has the shortest calling syntax:

    public void method(Object... args) {
        if (args.length % 2 != 0) throw new IllegalArgumentException();
        for (int i = 0; i < args.length; i += 2) {
            String s = (String)args[i + 0];
            int i = (Integer)args[i + 1];
    
            ...
        }
    }
    
  4. Use a builder-style object:

    public Pairs method() {
        return new Pairs();
    }
    
    // make the names here meaningful for what your method actually does
    public static class Pairs {
        private static class Pair {
            String s;
            int i;
        }
    
        private final List<Pair> pairs = new ArrayList<>();
    
        private Pairs() {}
    
        public Pairs add(String s, int i) {
            Pair p = new Pair();
            p.s = s;
            p.i = i;
            pairs.add(p);
            return this;
        }
    
        public void run() {
            for (Pair p : pairs) {
                ... do method's work here ...
            }
        }
    }
    

    Depending on what you want to achieve this might be over-complicating it, but it gives a quite pleasant and fully type-checked syntax for the caller:

    method()
        .add("a", 1)
        .add("b", 2)
        .add("c", 3)
        .run();
    
Boann
  • 48,794
  • 16
  • 117
  • 146
1

Make the argument one Object argument, which has its own problems...

public void foo(Object... things)

But probably the best idea is to use a generic list for each argument type :

public void foo(List<String> strings, List<Integer> integers) {}

If the method specifically requires matchigng pairs a Map<String, Integer> could also be used.

(no you can't to original question)

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
0

hmmm why don't you just mapping instead?

Something like this

public void foo(Map<String,Integer> map){


}

Or maybe instead of String and int, just use objects?

 public void foo(Object... args){

 }
nafas
  • 5,283
  • 3
  • 29
  • 57
  • Map would only allow two types, and well its nto really a map. Use two generic collecitons instead. – NimChimpsky Jun 23 '14 at 13:24
  • Yeah, question is kinda vague, but two generic collection would solve things – nafas Jun 23 '14 at 13:26
  • @vikingsteve Why the aversion towards that method? I was leaning towards dasblinkenlight's answer. – Legato Jun 23 '14 at 16:09
  • 1
    Since using `Object` is generally regarded as bad practise, at least since java 1.5. There is no type safety if someone uses `method("a", 1, "b", 2)` versus `method("a", "b", 1, 2)` -> such errors won't be apparent until run-time (and modern thinking is to catch as many errors at compile-time as possible) – vikingsteve Jun 23 '14 at 19:47