Return ArrayList or List?
I’m creating a library to be used by people but why should my method return a List instead of an ArrayList? Because if the user knows the real type is an ArrayList he will use the accessor [] in a loop instead of iterator but if he doesn’t know he will use an iterator. Same question for LinkedList, if the return type is a List he won’t be able to use the correct accessor. Am I right?
Depends how specific you want to be. Generally, using the Abstract parent class is better, it allows people to store the array you’re returning in whatever structure implementing List they want.
Always program to the interface when possible. What did you think the iterator for an arraylist does internally? 🙂
Well, I’d most likely use a foreach loop and I can’t remember when I last used the direct accessor on an ArrayList . If you always iterate over the list anyways you can as well use an iterator.
How, exactly, do you want to use [] on a list? I always access my lists elements with get(int) , which works on any list type.
8 Answers 8
Returning List will make it possible for users of your library to use anything that implements a List interface, while using an ArrayList will force them to use an ArrayList.
If in the future, you as a library creator decide to change your internal implementation, that changes will be hidden from the end user by the generic interface to your library.
Ok but if i have created in my method a List
Yes but that doesn’t matter, you just specify with the interface that it’s a List , but then the user can choose the implementation
@BaL could you explain what it means that the user can choose the implementation? If the library function returns a List backed by an ArrayList, the user cannot choose to treat it the same as a LinkedList, e.g., the List will not respond to getFirst() or getLast()
@cyang Both parties are a bit more free — it is easy for the end user to convert a List to something more specific (see James Poulson’s answer), but a bit harder to do so from one specific implementation to other. Perhaps more importantly, library creator can trivially change the internal implementation without breaking client code. It is a general principle, which is not as apparent with this particular example (because Java provides rich functionality for manipulating lists).
@cyang Let’s say you have a class for reading from a database. It has a method to return a reader class. That class could read from an Oracle database, MSSQL or something as simple as a text file. It might be returning a OracleReader , a MsSqlReader or a FileReader , and each of them will implement a countRows() method. As an end-user you really don’t care about the type of the database. Instead of that, the class might return a DatabaseReader , and you as an end user could then use countRows() on that. If the database changes, your code is still okay.
Because the users of your library should never know that you are using an ArrayList internally.
For example, say you return an ArrayList and lots of people have started using your library. Now if you suddenly realize a LinkedList better suits your purpose, then you break compatibility for all the folks who are presently using your code.
This is why it is always better to code to an interface, not an implementation, and even more so when you are writing code that is specifically meant to be re-used. The interface (List in this case) acts as a contract between your code and the client’s code. It tells them what your code does (interface), without telling them how it does it (by not exposing the implementation).
return an ArrayList method
This is a drive method for two other classes. which i posted here https://codereview.stackexchange.com/questions/33148/book-program-with-arraylist I need some help for the private static ArrayList getAuthors(String authors) method. I am kind a beginner. so please help me finish this drive method. or give me some directions. Instruction some of the elements of the allAuthors array contain asterisks “*” between two authors names. The getAuthors method uses this asterisk as a delimiter between names to store them separately in the returned ArrayList of Strings.
import java.util.ArrayList; public class LibraryDrive < public static void main(String[] args) < String[] titles = < "The Hobbit", "Acer Dumpling", "A Christmas Carol", "Marley and Me", "Building Java Programs", "Java, How to Program" >; String[] allAuthors = < "Tolkien, J.R.", "Doofus, Robert", "Dickens, Charles", "Remember, SomeoneIdont", "Reges, Stuart*Stepp, Marty", "Deitel, Paul*Deitel, Harvery" >; ArrayList authors = new ArrayList(); ArrayList books = new ArrayList(); for (int i = 0; i < titles.length; i++) < authors = getAuthors(allAuthors[i]); Book b = new Book(titles[i], authors); books.add(b); authors.remove(0); >Library lib = new Library(books); System.out.println(lib); lib.sort(); System.out.println(lib); > private static ArrayList getAuthors(String authors) < ArrayList books = new ArrayList(); // need help here. return books; > >
try the authors.split function, it takes a regex, have a look at other methods available in String, it helps knowing them
Java Returning method which returns arraylist?
1. If that class from which you want to call this method, is in the same package, then create an instance of this class and call the method.
2. Use Composition
3. It would be better to have a Generic ArrayList like ArrayList etc.
public class Test < public ArrayListmyNumbers() < ArrayListnumbers = new ArrayList(); numbers.add(5); numbers.add(11); numbers.add(3); return(numbers); > > public class T < public static void main(String[] args)< Test t = new Test(); ArrayListarr = t.myNumbers(); // You can catch the returned integer arraylist into an arraylist. > >
Assuming you have something like so:
public class MyFirstClass < . public ArrayListmyNumbers() < ArrayListnumbers = new ArrayList(); numbers.add(5); numbers.add(11); numbers.add(3); return(numbers); > . >
You can call that method like so:
public class MySecondClass < . MyFirstClass m1 = new MyFirstClass(); ListmyList = m1.myNumbers(); . >
Since the method you are trying to call is not static, you will have to create an instance of the class which provides this method. Once you create the instance, you will then have access to the method.
Note, that in the code example above, I used this line: List myList = m1.myNumbers(); . This can be changed by the following: ArrayList myList = m1.myNumbers(); . However, it is usually recommended to program to an interface, and not to a concrete implementation, so my suggestion for the method you are using would be to do something like so:
public List myNumbers() < Listnumbers = new ArrayList(); numbers.add(5); numbers.add(11); numbers.add(3); return(numbers); >
This will allow you to assign the contents of that list to whatever implements the List interface.
How to return Array Values as a output to a Method in Java
I am new to Java .I am working on my previous post link. I want to return specific extension(like .txt ) file names under directory. For this,I wrote the following method with 2 arguments.
public void ListOfFileNames(String directoryPath,String fileType) < //Creating Object for File class File fileObject=new File(directoryPath); //Fetching all the FileNames under given Path File[] listOfFiles=fileObject.listFiles(); //Creating another Array for saving fileNames, which are satisfying as far our requirments String[] fileNames; for (int fileIndex = 0; fileIndex < listOfFiles.length; fileIndex++) < if (listOfFiles[fileIndex].isFile()) < //True condition,Array Index value is File if (listOfFiles[fileIndex].getName().endsWith(fileType)) < //System.out.println(listOfFiles[fileIndex].getName()); >> >
8 Answers 8
It is good to use List instead of array
Change your code like this
public void FileMoving() < //created object for Class ExternalFileExecutions ExternalFileExecutionsObject=new ExternalFileExecutions(); //calling Method from class object ListfileNames = ExternalFileExecutionsObject.ListOfFileNames("C:/Documents and Settings/mahesh/Desktop/InputFiles",".txt"); //to find out the length of list System.out.println(fileNames.size()); > public List ListOfFileNames(String directoryPath,String fileType) < //Creating Object for File class File fileObject=new File(directoryPath); //Fetching all the FileNames under given Path File[] listOfFiles=fileObject.listFiles(); //Creating another Array for saving fileNames, which are satisfying as far our requirments ListfileNames = new ArrayList(); for (int fileIndex = 0; fileIndex < listOfFiles.length; fileIndex++) < if (listOfFiles[fileIndex].isFile()) < //True condition,Array Index value is File if (listOfFiles[fileIndex].getName().endsWith(fileType)) < //System.out.println(listOfFiles[fileIndex].getName()); fileNames .add(listOfFiles[fileIndex].getName()); >> > return fileNames ; >
,I just copied entire your code in place my code. it showing following error The type list is not generic it cannot be parameterized with arguments
@ur truly friend what is your import statement it should be import java.util.List; not import java.awt.List; .
again I got the following error. ArrayList cannot be resolved to a type at line List
The return type should be String[] or List you need to put every file name you encounter that fulfils your criteria into the list or array and return the same in the end.
If you are using Arrays
String[] fileNames; int count = 0; if (listOfFiles[fileIndex].getName().endsWith(fileType)) < fileNames[count] = listOfFiles[fileIndex].getName(); count++; >return fileNames;
The rest of the code remains same.
In case you want to do it Using List
List fileNames = new ArrayList(); if (listOfFiles[fileIndex].getName().endsWith(fileType)) < fileNames.add(listOfFiles[fileIndex].getName()); >return fileNames;
public List getListOfFileNames(String directoryPath, String fileType) < Listresult = new ArrayList(); // add the code to loop over the director list and add them to the result return result; >
An even better solution would be to use the list() method that’s build into the File class. Pass it a FilenameFilter .
The best thing to do is reuse code rather than write it again.
For return type change your first line to
public String[] ListOfFileNames(String directoryPath,String fileType)
As for adding an item in array, you might want to consider using ArrayList instead. Like so:
List stringList = new ArrayList(); stringList.add("string")
public List ListOfFileNames(String directoryPath, String fileType) < //Creating Object for File class File fileObject = new File(directoryPath); //Fetching all the FileNames under given Path File[] listOfFiles = fileObject.listFiles(); //Creating another Array for saving fileNames, which are satisfying as far our requirments ListfileNames = new ArrayList(); for (int fileIndex = 0; fileIndex < listOfFiles.length; fileIndex++) < if (listOfFiles[fileIndex].isFile()) < //True condition,Array Index value is File if (listOfFiles[fileIndex].getName().endsWith(fileType)) < //System.out.println(listOfFiles[fileIndex].getName()); fileNames.add(listOfFiles[fileIndex].getName()); >> > return fileNames; >
You want to return several String from your method. So it should return a String[] or a List , for example.
You also want to respect the Java naming conventions, so the method should be declared as:
public String[] listOfFileNames(String directoryPath, String fileType)
If you read the javadoc of java.io.File , you’ll notice that there is a method which does exactly that. You just need to pass a FilenameFilter , which tells the methof which file names should be returned:
public String[] listOfFileNames(String directoryPath, final String fileType) < return new File(directoryPath).list(new FilenameFilter() < @Override public boolean accept(File dir, String name) < return name.endsWith(fileType); >>); >
This code above uses an anonymous inner class, which implements the FilenameFilter interface. Read the Java tutorial to learn about them.
I would usually prefer to return a File instead of a String . That way you don’t have to create a new file each time you want to work with it and you can access for example the file name ( .getName() > foo.txt ) or the whole path ( getPath() > /dir/foo.txt ) depending on what you need.
File already has a built-in filter functionality, either working on the file as String ( FileNameFilter ) or on the File itself ( FileFilter ). As above, I would prefer working on the File .
Implementing a FileFilter is pretty simple.
private static class ExtensionFilter implements FileFilter < private final String extension; public ExtensionFilter(String extension) < // store ".TXT" this.extension = "." + extension.toUpperCase(Locale.ROOT); >@Override public boolean accept(File pathname) < // return true if it is a file and it ends with .TXT return pathname.isFile() && pathname.getName().toUpperCase(Locale.ROOT).endsWith(extension); >>
Now add some methods that use such a filter and you are pretty much done.
// internal method that lists files, converts them into a List and makes sure it does not return null private static List listFilesWithExtension(File directory, ExtensionFilter filter) < File[] files = directory.listFiles(filter); return files != null ? Arrays.asList(files) : Collections.emptyList(); > /** use like listFilesWithExtension(directory, "txt") */ public static List listFilesWithExtension(File directory, String extension) < return listFilesWithExtension(directory, new ExtensionFilter(extension)); >/** lists only .txt files */ private static final ExtensionFilter TXT_FILES = new ExtensionFilter("txt"); public static List listTxtFiles(File directory)
If you actually want a list / array of Strings you can convert it later via methods like
public static String[] getFileNamesFromFiles(List files) < String[] result = new String[files.size()]; for (int i = 0; i < files.size(); i++) < File file = files.get(i); result[i] = file.getName(); >return result; >