2

Sorry for stupid question... Could anybody help me with returning two variable from method (I read here and tried to recode but without result).

public class FileQualityChecker {
    EnviroVars vars = new EnviroVars();  
    public int n = 0;
    public int z = 0;
    public int m = 0;
    String stringStatus;


    public void stringLenghtCheck(String pathToCheckedFile)
    {
        try{    
    FileInputStream fstream = new          FileInputStream(pathToCheckedFile+"\\"+"Test.dat");
         // Get the object of DataInputStream
         DataInputStream in = new DataInputStream(fstream);
         BufferedReader br = new BufferedReader(new InputStreamReader(in));
         String strLine;
          //Read File Line By Line
         while ((strLine = br.readLine()) != null)   
         {

           if  (
           strLine.length() == vars.strLenghtH ||
           strLine.length() == vars.strLenghtCUoriginal ||
           strLine.length() == vars.strLenghtCEAoriginal ||
           strLine.length() == vars.strLenghtCAoriginal ||
           strLine.length() == vars.strLenghtTrailer ||
           strLine.length() == vars.strLenghtLastRow 

           ) 
            {
               stringStatus = "ok";
               n++;
               z++; 

            }
           else 
           {
                stringStatus = "Fail";
                n++; 
                m++;
                }
           System.out.println (n +" " + strLine.length() +" " + stringStatus);
          }



         //Close the input stream
          in.close();
        }
        catch
        (Exception e){//Catch exception if any
         System.err.println("Error: " + e.getMessage());
         }

         /*How to return m and z from method to use these vars for writing in the file*/
         return (m, z);


        }

}

I need m and z in another class for write them into file. Thank you.

May12
  • 2,420
  • 12
  • 63
  • 99
  • I would move your fields to be local variables where possible. – Peter Lawrey Aug 15 '12 at 11:23
  • Please don't use DataInputStream if you are reading text. – Peter Lawrey Aug 15 '12 at 11:24
  • And please don't use `tab` in your code. I hate tabs... Totally different settings depending on your favorite IDE. Just use spaces instead. – maba Aug 15 '12 at 11:27
  • why DataInputStream is a bad way to read a file? – May12 Aug 15 '12 at 11:29
  • 2
    @maba: OMG. use tabs! When you use tabs, everyone can view your file with his / her favorite tab width setting. With spaces, you enforce your personal preferences onto others. Read this: http://lea.verou.me/2012/01/why-tabs-are-clearly-superior/ . never, never use spaces for indentation. Really. It's the most annoyuing thing in source code you can possibly image. – Polygnome Aug 15 '12 at 11:40
  • @Polygnome So if you paste some code with tabs here on SO, do you think that it looks good and is readable??? – maba Aug 15 '12 at 11:42
  • 1
    I think Tuples is something you may look into: http://stackoverflow.com/questions/2670982/using-tuples-in-java – ThiamTeck Aug 15 '12 at 11:43
  • @maba: If you do it right, yes, sure. – Polygnome Aug 15 '12 at 11:44
  • @Polygnome Well should you even have to *do it right*? Isn't copy-paste how you should do it? – maba Aug 15 '12 at 11:45
  • Just as a tip, I'd pull out the string length into a separate variable so that you don't have to get it multiple times. For example: int stringLength = strLine.length(); Speaking of length, I noticed your method name is not spelled correctly: should be stringLengthCheck instead of stringLenghtCheck. – Makotosan Jan 09 '14 at 21:35

11 Answers11

10

My first question with these sort of issues is, what's the relationship between these two results ?

If they're unrelated, does that point to your method doing two different things ?

If they're related (they appear to be in this case), then wrap them in a custom object. This gives you the chance to add more results later into this object, and you can attach behaviour to this object.

Your other solution is to pass a callback object into this method, so you don't return anything at all, but rather your method then calls a method on this object e.g.

// do some processing
callbackObject.furtherMethod(m, n);

This has the advantage of following the OO principle of getting objects to do things for you, rather than asking them for info and doing it yourself.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • they are related. "m" shows number of strings with incorrect lenght and z - with correct lenght. – May12 Aug 15 '12 at 11:23
6

create a separate class and have m and z as variables in that object , create and populate that object and return that object

class result {
  int m ; 
  int z ; 

// define getters and setters 
} 

public result stringLengthCheck(String pathToFile)
{

// your code 

result r = new result();
r.setM(m);
r.setZ(z);
return r ;
}
Rocky
  • 941
  • 7
  • 11
  • Alternatively, if possible, return an array of these objects. Another valid method (though probably not preferable) is using class variables. And damn, you beat me to it :P – ATaylor Aug 15 '12 at 11:13
4

how about return a map. eg:

Map<String,Integer> result = new HashMap<String,Integer>();
result.put("ok",m);
result.put("fail",z);
return result;

and your method should be changed to:

public Map stringLenghtCheck(String pathToCheckedFile)

at last, you could get the result by checking out the map:

map.get("ok")
map.get("fail")
bosshida
  • 51
  • 2
4

You cannot return more than one variable from method. You need to return something else instead. There many suggestions can take place:

  1. set these variables in class where your method is, and then access them (outside this class?)
    • plus: simple notation like set and get
    • plus: never mix up your variables
    • minus: some garbage in class
  2. return an array or list with variables
    • plus: simplicity of storing
    • plus: possibility to iterate over the data
    • minus: you can easily mix up variables (need convention about variables' places)
    • minus: extra memory allocation - may be sufficient when storing few variables
  3. return a wrapper (instance of class that contains needed variables)
    • plus: simplicity of storing and reading
    • plus: never mix up your variables
    • minus: ugly code (possibly) if wrapper is not frequently-used
  4. use callback (like void setToArray(int[] array, args...)) - the same +/- that 1-3 points say and

    • plus: memory allocation decrease is possible
    • minus: more ugly method signature

    And some hacks (hacks - not for casual cases!) also can take place:

  5. use concatenation. You can join several strings in one by using delimiters, or store two integers in long

    • all possible minuses, no pluses, but funny
  6. use InputStream and OutputStream
    • plus: possibility of usage all the code for stream handling (storing/reading to file, for example)
    • minus: no random access to data
  7. use Iterator (I placed it under 'hacks' only because in many ways it assumes storing variables like in wrapper)
    • plus: possibility to iterate over the data
    • plus: possibility to avoid extra memory allocation
    • minus: no random access to data
  8. store all in String (or byte[]) and parse when needed
    • plus: String can be transmitted anyhow
    • minus: parsing is an expensive procedure

For storing two integers Point and Dimension classes are often used. But for code given I would suggest simple array usage or storing variables in class FileQualityChecker, because m and z don't seem to fit to coordinates or dimensions context.

Sergey Fedorov
  • 2,169
  • 1
  • 15
  • 26
1

You could create a custom class or return a list:

return Arrays.asList(m, z);

(the return type of your method would be List<Integer>)

Or in your case, since m and z are class members, you could return nothing (void) and provide getters to get the values of m and z once the method has returned.

assylias
  • 321,522
  • 82
  • 660
  • 783
1

No you can't but it is easy to write a class that would contain those fields:

class StrAndInt {
   String str;
   int num;

   StrAndInt(String str, int num) {
       this.str = str;
       this.num = num;
   }
}

class MyApplication {
   ....
   ....
   StrAndInt myMethod() {
      ....
      ....
      return new StrAndInt("The value returned", 10);
   }
Lars
  • 947
  • 8
  • 15
1

Another option is to not return anything as you have the results in fields you can use other methods to obtain these.

FileQualityChecker fqc = ..

fqc.stringLenghtCheck(fileName);
int okCount = fqc.getOkCount();
int failedCount = fqc.getFailedCount();
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

I don't think you can return two variables from a method as a method can have only one return type. So IMO you have two options:

1) Create a class with the same type of variables and generate getter-setter for those variables you defined in that class. Now from the method from where you want to return the variables create the object of that class and use setters to set the value of instance variables with the value of variables you want to return return that object.

2) Create an array of those variables and return that array.

Sandeep Kumar
  • 13,799
  • 21
  • 74
  • 110
0

1.I hope m and n uses pass by values. 2.Instead use Pass by Reference.To do Pass by Reference in Java, it has to be a Java Object. 3.So create new Integer object m=new Integer();.

Prem Chandran
  • 55
  • 1
  • 2
  • 8
0

You could place both variables in an int[] and extract both values when you call the method.

return new Integer[]{m, z};

After calling the method:

Integer[] array = Foo.method();
int m = array[0];
int z = array[1];
Curlip
  • 395
  • 1
  • 3
  • 15
0

You could simply construct an object.

However, if you must return more than one variable, you can return an array of similarly typed variables, example below:

public static StringBuilder[] remedySBarrayreturner() {
    sbbb.append("huhu");
    sbcc.append("hihi");
    return new StringBuilder[] {sbbb, sbcc};
}
Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38