In Java, I have a following declaration:
public List<File> getAllFiles(){
return Collections.unmodifiableList(createdFiles);
}
I want to access the object (file) that is first on that list. How can I best do it?
getAllFiles().iterator().next();
or
getAllFiles().get(0);
File file = getAllFiles().get(0);
Remember to check whether the list is empty.
List<File> allFiles = getAllFiles();
if (allFiles.size() == 0) {
// handle this situation as you like.
} else {
File file = allFiles.get(0);
// ...
}
Since you want the first element I think you should avoid to the iterator approach as, depending on the implementation, you would create a object unnecessary: the iterator.
Related
I want to return a ArrayList and a File Array with one method. For more Background(isnt necessary to help me) you can read the rest.
I am coding my version for the Sokoban game. For that i have to get a List(in my case a ArrayList) with all the paths of the levels so i can get the information and I also need the File Array because i used in a previous version and it would take hours to change that. The input for the method is "level" at the moment. Thats the directory with the .xsd files.r
I cant rly change the things i want to return.
public static ArrayList<SokobanLevel> loadLevels(String dirPath) throws SokobanException {
Path dir =
FileSystems.getDefault().getPath(dirPath).toAbsolutePath();
File[] fileFolder = dir.toFile().listFiles();
ArrayList<SokobanLevel> allLevel = new ArrayList<SokobanLevel>();
for(int i = 0; i < fileFolder.length; i++) {
SokobanLevel sl = new
SokobanLevel(fileFolder[i].getAbsolutePath());
sl.setId(i);
allLevel.add(sl);
}
//would like to also return File[] fileFolder
return allLevel;
}
method works so far so good.
Just make a tuple like this:
Class Result {
public static final ArrayList list;
public static final File[] files;
public Result(ArrayList list,File[] files){
this.list =list;
this.files = files;
}
}
And use it like this:
return new Result(list,files)
When you need to use the list:result.list.
When you need to use the files:result.files.
It's read-only because it's qualifies wiht final keyword.
You cannot return multiple objects from one method. You can put the different objects in an new class and then return that.
I would like to make my code look more efficient. Currently I got something like this:
private static String[] getAllFilesFromDirectory(String path) {
File file = new File(path);
String fileNamePattern = file.getName() + ".*\\.[0-9]*\\.GOOD";
File dir = new File(file.getParent());
String[] files = dir.list((currDir, currName) -> currName.matches(fileNamePattern));
return files;
}
private static List<Integer> getAllFileNumbers(String path) {
String[] files = getAllFilesFromDirectory(path);
List<Integer> fileNumbers = new ArrayList<>();
for (String currentFile : files) {
fileNumbers.add(extractFileNumber(currentFile));
}
return fileNumbers;
}
private static Integer extractFileNumber(String fileName) {
return Integer.parseInt(fileName.split("\\.")[2]);
}
First thing first. To getAllFileNumbers method I am passing path to directory, after that I am getting array of files in this directory with specific pattern. And from every file I need to extract number.
Example:
test.txt.1.fail
test2.txt.2.good
test3.pdf.1.good
Here I am returning list of following numbers : 1, 2, 1.
What I would like to change? Probably use stream api instead of foreach loop.
First idea was something like this:
Arrays.stream(files).map(this::extractFileNumber).collect(Collectors.toList());
But because the methods are static i cant use it like this.
Obviously I could move extractFileNumber inside of lambda but I would like to keep my method separately.
Maybe someone has other ideas, please feel free to post any ideas. Cheers!
Use stream api can make it shorter, suppose extractFileNumber is in class Main:
return Stream.of(files).map(Main::extractFileNumber).collect(Collectors.toList());
Hi there I have a problem dealing with some legacy code.
I need a way to get the changed File from the parseFile() method up to the calling doWithFileList() method.
public static void main(String[] args) throws IOException {
File file1 = File.createTempFile("file1", ".tmp");
File file2 = File.createTempFile("file2", ".tmp");
ArrayList<File> fileList = new ArrayList<File>();
fileList.add(file1);
fileList.add(file2);
doWithFileList(fileList);
}
static void doWithFileList(List<File> fileList) {
for (File file : fileList) {
String result = parseFile(file);
}
//Do something with the (now incorrect) file objects
for (File file : fileList) {
// always false here
if (!file.exists()) {
System.out.println("File does not exist anymore");
}
}
}
private static String parseFile(File file) {
//1. Get information from the File
//2. Use this information to load an object from the Database
//3. return some property of this object
//4. depending on another property of the DB object rename the file
file.renameTo(new File(file.getAbsoluteFile() + ".renamed"));
return "valueParsedFromFile";
}
I know that File objects are immutable.
The problem is in my real world problem the parseFile() method at the moment only does Step step 1-3 but I need to add step 4.
The renaming is not a problem, but I need to get the new file name somehow to the calling method.
in the real life problem there is bigger stack trace across multiple objects between those methods.
What would be the best way to get the changed name of the file back to the beginning of the the call hierarchy where I can change the object in the list.
my best guess at the moment would be to create a ReturnObject that holds both the String to return and the new File object. But then I have to refactor a bunch of methods on my way up so I would need to create a bunch of different return objects.
The following possiblities come to mind:
pass a mutable object, e.g. a new String[1] and set it there. (Mega-ugly, because you have side effects and not a pure function anymore) (On the other hand: you already have side-effects - go figure ;-))
Use a generic return object like String[], a Map, a Pair-implementation that you can find in various utilities (e.g. org.colllib.datastruct.Pair)
Use a hand-crafted return object
Personally, I'd probably go with (2), but it also might be (3)
Using a ReturnObjet seem to be the sole solution as far as I know.
I am attempting to write code to traverse a collection of type InstallationComponentSetup:
java.util.Collection<InstallationComponentSetup> components= context.getInstallationComponents();
Iterator it = components.iterator();
while (it.hasNext())
{
if (((InstallationComponentSetup)it).getName() == "ACQ")
{
return true;
}
}
The cast in the if-statement fails, but I don't really know why (I am a C++ programmer!).
If someone could give me some pointers as to what I am doing wrong I would be grateful.
it is an Iterator, whereas it.next() is an InstallationComponentSetup.
The error results from the fact that an Iterator cannot be cast as an InstallationComponentSetup.
Also, you shouldn't even need to cast if you parametrize the Iterator appropriately:
Iterator<InstallationComponentSetup> it = components.iterator();
Finally, don't compare strings with something like a == b, instead use a.equals(b). See "How do I compare strings in Java" for further details.
You might also want to look into the for-each loop if all you want to do is iterate over the collection. Your code can be rewritten as:
for (InstallationComponentSetup component : components)
if (component.getName().equals("ACQ"))
return true;
If you are comparing String , use equals() method .
Even your casting is wrong.You have to invoke next() on the iterator to get the next element . Hence it.next() gives you the next element which will be an object of InstallationComponentSetup, it is not of type InstallationComponentSetup hence the cast will fail.
Here you are casting the Iterator to your class type which will fail.
if (((InstallationComponentSetup)it).getName() == "ACQ")
{
return true;
}
I believe there is no need of cast here as you have defined the Collection to hold the specific type of element and also if you declare the Iterator of a specific type.
You can simply do :
// define Iterator of InstallationComponentSetup
Iterator<InstallationComponentSetup> it = components.iterator();
if("ACQ".equals(it.next().getName())) {
return true;
}
You can also consider using the enhanced for loop in Java , if your purpose is only to read the elements .
for(InstallationComponentSetup component: components) {
if("ACQ".equals(component.getName())) {
return true;
}
}
You have to retrieve the next element in the iteration before you compare:
InstallationComponentSetup next = it.next();
if (next.getName() == "ACQ")
{
return true;
}
Try to use the following code. It is more concise and easier to understand.
Collection<InstallationComponentSetup> components= context.getInstallationComponents();
for(InstallationComponentSetup comp : components){
if("ACQ".equals(comp.getName()){
return;
}
}
I think you had two problems in you code.
Cast the iterator to an object doesn't work like that. You need to use it.next() to get the object and move the iterator.
like already mentioned you need equals to compare Strings. == compares "memory locations" (in C++ terms).
Use it.next() to get the next element.
Also, use the .equals() method to compare strings in Java. Otherwise, the references are compared.
Finally, the cast should be unnecessary with a type-parameterized Iterator.
while (it.hasNext())
{
if ( it.next().getName().equals("ACQ") ) {
...
}
}
You have to retrieve the next element in the iteration before you compare:
java.util.Collection<InstallationComponentSetup> components= context.getInstallationComponents();
Iterator<InstallationComponentSetup> it = components.iterator();
while (it.hasNext()) {
if ("ACQ".equals(it.next().getName())) {
return true;
}
}
It would be easier to use foreach loop, make use of generic type, use equals for String and change string comparison order to be null secure.
Collection<InstallationComponentSetup> components= context.getInstallationComponents();
for (InstallationComponentSetup setup : components)
{
if ("ACQ".equals(setup.getName()))
{
return true;
}
}
The install4j API is still for Java 1.4, so there are no generics yet. This will work:
for (Object o : context.getInstallationComponents()) {
InstallationComponentSetup component = (InstallationComponentSetup)o;
if (component.getName().equals("ACQ")) {
return true;
}
}
Say I have already created an iterator called "iter" and an arraylist called "database". I want to be able to look through the arraylist and see if any element in the arraylist is equal to a String called "test". If it is, then I would like to add the element to another list.
while(iter.hasNext()) {
if(database.next() == test) {
database.next().add(another_list);
}
}
What am I doing wrong? I'm completely new to iterators in java. Do I need to write my own iterator class? Any code examples would be greatly appreciated. Thanks
The problem with your code is that every time you call .next(), it advances the iterator forward to the next position. This means that this code
if(database.next() == test) {
database.next().add(another_list);
}
Won't work as intended, because the first call to database.next() will not give back the same value as the second call to database.next(). To fix this, you'll want to make a temporary variable to hold on to the new value, as seen here:
while(iter.hasNext()) {
/* type */ curr = iter.next();
if(curr == test) {
curr.add(another_list);
}
}
(Filling in the real type of what's being iterated over in place of /* type */)
In many cases, though, you don't need to use iterators explicitly. Most of the Collections types implement the Iterable interface, in which case you can just write
/* container */ c;
for(/* type */ curr: c) {
if(curr == test) {
curr.add(another_list);
}
}
Hope this helps!
if(database.contains("test"))
{
another_list.add("test");
}
you can use the built in method contains(...)
you should use equals(...) for data comparisions
look at the javadoc to see if there is already a method present for your purpose