2

My for loop is too long. As demo there is three for loops going on for methodB. Is there a way I could reduce this to a short for loop (one for loop)? Thanks

    public class MyMates  
    {

       private static TreeSet<String> myTable = new TreeSet<String>();

       private static String[] names1 = null;
       private static String[] names2 = null;
       private static String[] names3 = null;


       public MyMates()
       {
        super();
        myTable = new TreeSet<String>();
       }


       public  static String methodA(String aTemp)
       {
         String[] names1 = new String[] {"Amy", "Jose", "Jeremy", "Alice", "Patrick"};
         String[] names2 = new String[] { "Alan", "Amy", "Jeremy", "Helen", "Alexi"};
         String[] names3 = new String[] { "Adel", "Aaron", "Amy", "James", "Alice" };

         return aTemp;
      } 



    public static String methodB(String bTemp)
     {

        for (int i = 0; i < names1.length; i++) {
        myTable.add(names1[i]);
        }
        System.out.println(myTable);

        for (int i = 0; i < names2.length; i++) {
        myTable.add(names2[i]);
        }
        System.out.println(myTable);

       for (int i = 0; i < names3.length; i++) {
       myTable.add(names3[i]);
       }
       System.out.println(myTable);

    return bTemp;
   }

enter code here

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
DiscoDude
  • 617
  • 3
  • 17
  • 39
  • Imo, the for loops given here aren't bad. If you had, say, 5 or more names arrays (instead of 3), or more instances of having to do the same thing N times (once for each names array), then it would definitely be worthwhile to refactor. – jyoungdev Jul 16 '10 at 14:25

7 Answers7

9

Actually, you don't need any for loop:

myTable.addAll(Arrays.asList(names1));
myTable.addAll(Arrays.asList(names2));
myTable.addAll(Arrays.asList(names3));
Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
8

On extract method refactoring

When you have something like this (in pseudocode):

doA(x);
doB(x);
doC(x);

doA(y);
doB(y);
doC(y);

You can often (though not always) extract doA/doB/doC and refactor into a method doABC like this:

void doABC(o) {
  doA(o);
  doB(o);
  doC(o);
}

Then elsewhere you do:

doABC(x);
doABC(y);

This is called extract method refactoring.


On for-each loop

Since 1.5, the for-each loop is added for arrays and instances of Iterable. Here's a simple example:

    String[] names = { "Alice", "Bob", "Carol" };
    for (String name : names) {
        System.out.println(name);
    }
    // "Alice", "Bob", "Carol"

A quote from Effective Java 2nd Edition, Item 46: Prefer for-each loops to traditional for loops:

The for-each loop, introduced in release 1.5, gets rid of the clutter and the opportunity for error by hiding the iterator or index variable completely. The resulting idiom applies equally to collections and arrays:

// The preferred idiom for iterating over collections and arrays
for (Element e : elements) {
    doSomething(e);
}

When you see the colon (:), read it as "in." Thus, the loop above reads as "for each element e in elements." Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary for loop in some circumstances, as it computes the limit of the array index only once.

The for-each loop is not applicable to all cases, but when it does, you should always try to use it to improve readability and minimize chances of errors.

See also


On Collection.addAll

Collection<E> defines addAll(Collection<? extends E> that can be used to add all elements from one Collection to another (assuming it's typesafe).

Moreover, there's Arrays.asList(T...) that can create a List backed by an array of references (not primitives!).

This means that in this case you can do:

myTable.addAll(Arrays.asList(names1));
myTable.addAll(Arrays.asList(names2));
myTable.addAll(Arrays.asList(names3));

Note that a common pitfall is to pass, e.g. an int[] to Arrays.asList, and hoping to get a List<Integer>. This doesn't work, because while an int is autoboxable to an Integer, an int[] is NOT autoboxable to an Integer[].

Related questions


On local variables

You've written the following:

public class MyMates  {
   private static String[] names1 = null;
   private static String[] names2 = null;
   private static String[] names3 = null;

   public  static String methodA(String aTemp) {
     String[] names1 = ...;
     String[] names2 = ...;
     String[] names3 = ...;

     return aTemp;
   }

It needs to be said that the assignments in methodA are to locally declared variables names1, names2, names3 that shadows the fields with the same names. These variables goes out of scope at the end of methodA, and thus serve little to no purpose.

More often than not this is not what you want. You probably intent to assign to the fields instead, i.e.:

   public  static String methodA(String aTemp) {
     names1 = ...;
     names2 = ...;
     names3 = ...;

     return aTemp;
   }
Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
6

Implement a method addNames(String[] names) and call it 3 times.

This is called the "extract method" refactoring.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
4

An alternative which uses a 2 dimensional array and two nested loops (I don't understand parameter and return values in methods A/B)

public class MyMates {
    private static TreeSet<String> myTable = new TreeSet<String>();
    private static String[][] names;

    public MyMates() {
        super();
        myTable = new TreeSet<String>();
    }

    public static String methodA(String aTemp) {
        names = new String[][] {
                { "Amy", "Jose", "Jeremy", "Alice", "Patrick" },
                { "Alan", "Amy", "Jeremy", "Helen", "Alexi" },
                { "Adel", "Aaron", "Amy", "James", "Alice" } };

        return aTemp;
    }

    public static String methodB(String bTemp) {

        for (int row = 0; row < names.length; row++) {
            for (int i = 0; i < names[row].length; i++) {
                myTable.add(names[row][i]);
                System.out.println(myTable);
            }
        }
        return "";
    }

    public static void main(String[] args) {
        methodA("");
        methodB("");
    }
}
stacker
  • 68,052
  • 28
  • 140
  • 210
  • I don't either, but this isn't an answer, it's a comment. – Jason S Jul 16 '10 at 12:51
  • its assignment. I have been asked to create different methods to do different things. The above is a demo not the actual assignment. The assignment asked for return values. In the next assignment I will be using lists etc, as it should be. – DiscoDude Jul 16 '10 at 12:53
  • This is a good answer. Generally, implementing variables x1, x2, ... xn is doing work that the computer can do for you--specifically, if you want the computer to understand the concept of "N variables of the same type" so that it can iterate through all of them, you need a collection (such as an array), as demonstrated in this answer. – jyoungdev Jul 16 '10 at 14:22
  • @dowln: you say this is an assignment, so please tag as "homework" – Jason S Jul 16 '10 at 16:17
3

why not use a 2d array?

 String[][] names = { {"Amy", "Jose", "Jeremy", "Alice", "Patrick"},
     { "Alan", "Amy", "Jeremy", "Helen", "Alexi"},
     { "Adel", "Aaron", "Amy", "James", "Alice" } };

 public static String methodB(String bTemp)
 {
     for (String[] namesarray : names)
     {
        for (String name : namesarray)
        {
           myTable.add(name);
        }
     }
     return bTemp;
 }

p.s. the methodA() / methodB() syntax is strange.... you are leaving yourself open to errors if the methodA() or methodB() is called more than once, or something uses myTable before methodA() and methodB() are both called.

Jason S
  • 184,598
  • 164
  • 608
  • 970
1

If you want only one for loop, you can first create an array (or a list) containing names1, names2 and names3.

Then you only have to loop on this new array/list.

Note : reset myTable which is static at each new instance (in the constructor) is curious...

Benoit Courtine
  • 7,014
  • 31
  • 42
  • I think the entire class is curious...but you can have a look at his 3 or 4 questions with his examples, it's always the same thing... – sly7_7 Jul 16 '10 at 12:52
0

Make a double loop:

String [] [] tableArray = new String [] [] {names1, names2, names3}
  for (int i = 0; i<tableArray.length; i++){
    for (int j = 0; j < tableArray[i].length; j++) {
    myTable.add(tableArray[i][j]);
    } }

Or you can perform a better algorithm for your homework, with a single loop, reducing the O(n^3) complexity to O(max(names1.length, names2.length, names3.length)) putting conditions and flags.

good luck with that one.

pampanet
  • 131
  • 6