11 Replies - 214 Views - Last Post: 12 July 2020 - 04:01 AM Rate Topic: -----

#1 flyingKakapo   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 25
  • Joined: 11-April 20

[JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 11:13 AM

So I'm working on a program that scans directories for file names, types, and their directories and saves them to a text file. An issue I discovered when I was reading through the program was when I sorted the filenames alphabetically, my other ArrayList containing the directories did not. After I realized this, I knew I couldn't alphabetize them like I did the ArrayList containing the filenames because the directory paths aren't alphabetized by filename (which makes sense).

I want to basically alphabetize my filename ArrayList, and make sure that the directory ArrayList indexes properly aligns with that list. I've thought of were to alphabetize/sort them as they're being added, then save the directory path to the ArrayList. The only reason I actually want to avoid this now is in case it'd be beneficial to throw these into a method that performs that task instead so that I can actively call it and modify the list indexes with a button press if need be as opposed to have a "set in stone" list.

Anyway here is my code:

package application;

import java.io.*;
import java.util.ArrayList;

public class Functions
{
	
	public ArrayList<String> listOfFiles = new ArrayList<>(); //made public to access in the controller
	public ArrayList<String> listOfParentDir = new ArrayList<>();
	public ArrayList<String> fileType = new ArrayList<>();
	
	public void listFilesInDirectory(final File folder)
	{
		int i = 0;
	    for (final File fileEntry : folder.listFiles()) 
	    {
	        if (fileEntry.isDirectory()) 
	        {
	            listFilesInDirectory(fileEntry);
	        } //recurisively checks if a directory, then makes it go through again if it is a folder and checks within
	        else 
	        {
	        	listOfFiles.add(fileEntry.getName());
	        	listOfParentDir.add(fileEntry.getParent());
	        	
	        	
	        	if (!fileType.contains(getFileType(i)))
	        	{
	        		fileType.add(getFileType(i));
	        	}//gets the file type only if it does not exist in the list keeping distinct instances only
	        	i++;
	        }//adds the contents to the object
	    }
	}
	
	public void alphabeticalSort(ArrayList<String> list)
	{
		String temp;

		for (int i = 0; i < list.size(); i++) 
        {
            for (int j = i + 1; j < list.size(); j++) 
            { 
                if (list.get(i).compareTo(list.get(j)) > 0)
                {
                    temp = list.get(i);
                    list.set(i, list.get(j));
                    list.set(j, temp);
                }
            }
        }
	}
	
	public String getFileName(int index)
	{
		return listOfFiles.get(index).substring(0, listOfFiles.get(index).length() - 4);
	}
	
	public String getFileType(int index)
	{
		return listOfFiles.get(index).substring(listOfFiles.get(index).length() - 3);
	}
	
	public String getParentDir(int index)
	{
		return listOfParentDir.get(index);
	}
	
	public String toString(int index)
	{
		return getFileType(index) + ", " + getParentDir(index) + ", " + getFileName(index);
	}
}




package application;


import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.ArrayList;
import javafx.event.ActionEvent;
import java.util.Scanner;
import javafx.scene.control.Control;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.Pane;
import javax.swing.JFileChooser;


public class jfsdcController extends Functions
{
	@FXML
	private TextField tbDirectory;

	@FXML
	private ComboBox<String> cbFileType;

	@FXML
	private Pane paneTabMain;

	@FXML
	private Pane paneTabSecond;

	@FXML
	private Label labelResults;


	@FXML
	public void btnBrowseClick(ActionEvent event)
	{
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(new java.io.File("C:\\"));
		chooser.setDialogTitle("Select Directory Path");
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		chooser.setAcceptAllFileFilterUsed(true);

		if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) 
		{
			tbDirectory.setText(String.valueOf(chooser.getCurrentDirectory()));
		}
		/*
		FileChooser fc = new FileChooser();
		File file = new File("filename");
		file = fc.showOpenDialog(jfsdcMain.primaryStage);// 07-07 opens dialog in file explorer
		 */
	}

	@FXML
	public void btnSearchClick(ActionEvent event) throws IOException
	{
		
		/*
		 * add a try catch so that it reverts back to the original class if it pulls null
		 */
		File desktopPath = new File (System.getProperty("user.home") +
				"\\Desktop\\ListOfFiles.txt");//saves file to desktop
		
		File directoryPath = new File(tbDirectory.getText());//directory is set by whatever the user inputs in the directory field
		
		PrintWriter pw = new PrintWriter(desktopPath);//this will create the file, passes through path set by desktopPath

		listFilesInDirectory(directoryPath);
		
		alphabeticalSort(listOfFiles);
		

			for(int i = 0; i < listOfFiles.size(); i++)
			{
				pw.println(toString(i));
			}
			
		//adds all the contents stored in the listOfFiles object to the text file
		pw.close();//flushes the printwriter and actually writes the text to the file
	}
}




This post has been edited by flyingKakapo: 11 July 2020 - 11:15 AM


Is This A Good Question/Topic? 0
  • +

Replies To: [JavaFX] Matching indexes of separate ArrayLists after sorting

#2 macosxnerd101   User is offline

  • Games, Graphs, and Auctions
  • member icon




Reputation: 12769
  • View blog
  • Posts: 45,954
  • Joined: 27-December 08

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 11:38 AM

Is there a reason you need parallel ArrayLists? Parallel arrays are not good practice. Java is an Object-Oriented language, and file directories are tree data structures. Why not try a more OO approach? This will also enable you to use Java's built in sorting functionality.
Was This Post Helpful? 1
  • +
  • -

#3 NormR   User is online

  • D.I.C Lover
  • member icon

Reputation: 836
  • View blog
  • Posts: 6,441
  • Joined: 25-December 13

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 11:41 AM

Quote

alphabetize my filename ArrayList, and make sure that the directory ArrayList indexes properly aligns with that list.

Can you give an example of what you are talking about. Does alphabetize mean to sort in alphabetic or natural order?
What does it mean "aligns with that list"?

Do you know about the Collections sort method? You could write a Comparator to handle any special ordering you want to do.
Was This Post Helpful? 0
  • +
  • -

#4 g00se   User is offline

  • D.I.C Lover
  • member icon

Reputation: 3704
  • View blog
  • Posts: 16,981
  • Joined: 20-September 08

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 11:53 AM

macosxnerd101 is right. Your data integrity is being compromised by its being separated. You should prefer File over String for that reason too, as it already contains hierarchic data

This post has been edited by g00se: 11 July 2020 - 11:54 AM
Reason for edit:: Fixed tag

Was This Post Helpful? 1
  • +
  • -

#5 flyingKakapo   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 25
  • Joined: 11-April 20

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 12:02 PM

View Postmacosxnerd101, on 11 July 2020 - 11:38 AM, said:

Is there a reason you need parallel ArrayLists? Parallel arrays are not good practice. Java is an Object-Oriented language, and file directories are tree data structures. Why not try a more OO approach? This will also enable you to use Java's built in sorting functionality.


There isn't really a reason I am, I just figured it was the best option. So according to that link you had, I should be storing a class object at each index? Also along with what NormR said, would I be able to use a comparator to organize the objects as needed?
Was This Post Helpful? 0
  • +
  • -

#6 NormR   User is online

  • D.I.C Lover
  • member icon

Reputation: 836
  • View blog
  • Posts: 6,441
  • Joined: 25-December 13

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 12:06 PM

Quote

would I be able to use a comparator to organize the objects as needed?

Can you give an example of what you are talking about?
Was This Post Helpful? 0
  • +
  • -

#7 flyingKakapo   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 25
  • Joined: 11-April 20

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 12:11 PM

View PostNormR, on 11 July 2020 - 11:41 AM, said:

Quote

alphabetize my filename ArrayList, and make sure that the directory ArrayList indexes properly aligns with that list.

Can you give an example of what you are talking about. Does alphabetize mean to sort in alphabetic or natural order?
What does it mean "aligns with that list"?

Do you know about the Collections sort method? You could write a Comparator to handle any special ordering you want to do.


"Aligns with that list" meant a parallel list, to which I've found out is bad practice so I'll try to avoid that.

I've never used them before so I will look into them and try them out.

View PostNormR, on 11 July 2020 - 12:06 PM, said:

Quote

would I be able to use a comparator to organize the objects as needed?

Can you give an example of what you are talking about?


So if instead of creating parallel arrays, I have 1 array of objects. Using a comparator, could I sort the ArrayList by the different object variables? The way I'm imagining this is an index of the ArrayList would contain an object with 3 string variables: fileType, fileName, filePath. Using the comparator, could I alphabetize (I don't believe I want natural order) based off of the fileType or fileName or filePath?

Another thing I was interested in was throwing the data into a datatable, then spitting it out to the file based off of how i have it currently organized in the datatable. That maybe a different question altogether so don't answer that one if that is the case.

This post has been edited by flyingKakapo: 11 July 2020 - 12:12 PM

Was This Post Helpful? 0
  • +
  • -

#8 NormR   User is online

  • D.I.C Lover
  • member icon

Reputation: 836
  • View blog
  • Posts: 6,441
  • Joined: 25-December 13

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 12:21 PM

Quote

Using the comparator, could I alphabetize (I don't believe I want natural order) based off of the fileType or fileName or filePath?

Yes, a Comparator tells the sort code which of the two objects it was given should go first.
Was This Post Helpful? 1
  • +
  • -

#9 g00se   User is offline

  • D.I.C Lover
  • member icon

Reputation: 3704
  • View blog
  • Posts: 16,981
  • Joined: 20-September 08

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 02:20 PM

Quote

ArrayList would contain an object with 3 string variables: fileType, fileName, filePath.

java.io.File already encapsulates at least two of those attributes - along with the attribute of parent. What do you understand by 'fileType'?

This post has been edited by g00se: 11 July 2020 - 02:21 PM
Reason for edit:: Clarification

Was This Post Helpful? 1
  • +
  • -

#10 flyingKakapo   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 25
  • Joined: 11-April 20

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 08:26 PM

Alright in case anybody was interested, here is what I've manage to come up with today in terms of my program. So I went back and did it as recommended and it certainly has helped out and taught me a lot of things I didn't know about java. I'm still working on it but I appreciate the advice given.

package application;


import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.Pane;
import javax.swing.JFileChooser;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.stream.Collectors;


public class jfsdcController extends Functions
{
	@FXML
	private TextField tbDirectory;

	@FXML
	private ComboBox<String> cbFileType;

	@FXML
	private Pane paneTabMain;

	@FXML
	private Pane paneTabSecond;

	@FXML
	private Label labelResults;


	@FXML
	public void btnBrowseClick(ActionEvent event)
	{
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(new java.io.File("C:\\"));
		chooser.setDialogTitle("Select Directory Path");
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		chooser.setAcceptAllFileFilterUsed(true);

		if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) 
		{
			tbDirectory.setText(String.valueOf(chooser.getCurrentDirectory()));
		}
		/*
		FileChooser fc = new FileChooser();
		File file = new File("filename");
		file = fc.showOpenDialog(jfsdcMain.primaryStage);// 07-07 opens dialog in file explorer
		 */
	}

	@FXML
	public void btnSearchClick(ActionEvent event) throws IOException
	{
		try
		{
			/*
			 * add a try catch so that it reverts back to the original class if it pulls null
			 */
			File desktopPath = new File (System.getProperty("user.home") +
					"\\Desktop\\ListOfFiles.txt");//saves file to desktop

			File directoryPath = new File(tbDirectory.getText());//directory is set by whatever the user inputs in the directory field

			listFilesInDirectory(directoryPath);
			initialize();//need to add files to combobox

			
			/*
			 * 			possibly can split this portion off as a separate button as the "execute" or "commit" button
			 */
			
			
			
			
			PrintWriter pw = new PrintWriter(desktopPath);//this will create the file, passes through path set by desktopPath

			sortAscFileTypes(fol);//modify as a button or possibly abstract class that determines which sort method used?

			for (FileObjects obj : fol)
			{
				pw.println(obj);
			}//adds all the contents stored in the listOfFiles object to the text file
			pw.close();//flushes the printwriter and actually writes the text to the file
		}
		catch (NullPointerException e)
		{
			//CREATE A POPUP HERE THAT STATES RETUNRS NO VALUES OR SOMETHING
		}
	}

	public void initialize()
	{
		ArrayList<String> distinctFileTypes = new ArrayList<>();
		for(int i = 0; i < fol.size(); i++)
		{
			if (!distinctFileTypes.contains(fol.get(i).getFileType()))
			{
				distinctFileTypes.add(fol.get(i).getFileType());//added solely because I can't check off the combobox
			}//if the filetype at that spot does not exist, it adds it to the list
		}		
		
		Collections.sort(distinctFileTypes);//sorts the list now alphabetically
		
		for (int i = 0; i < distinctFileTypes.size(); i++)
		{
			cbFileType.getItems().add(
					distinctFileTypes.get(i)
					);
		}//adds the alphabetically sorted list into the combobox
	}
}






package application;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Comparator;

public class Functions
{
	public ArrayList<String> listOfFiles = new ArrayList<>(); //made public to access in the controller
	public ArrayList<String> listOfParentDir = new ArrayList<>();
	public ArrayList<String> fileType = new ArrayList<>();

	FileObjects wordy = new FileObjects();
	List<FileObjects> fol = new ArrayList<>();

	public void listFilesInDirectory(final File folder)
	{
		for (final File fileEntry : folder.listFiles()) 
		{
			if (fileEntry.isDirectory()) 
			{
				listFilesInDirectory(fileEntry);
			} //recurisively checks if a directory, then makes it go through again if it is a folder and checks within
			else 
			{
				fol.add(new FileObjects(fileEntry.getParent(), fileEntry.getName()));

				//fileObjectList.add(fileObjects.toString());//the toString provides a get function and this stores it as a string and not an object

				/*
	        	listOfFiles.add(fileEntry.getName());
	        	listOfParentDir.add(fileEntry.getParent());


	        	if (!fileType.contains(getFileType(i)))
	        	{
	        		fileType.add(getFileType(i));
	        	}//gets the file type only if it does not exist in the list keeping distinct instances only
	        	i++;*/
			}//adds the contents to the object
		}
	}

	public void sortAscFileNames(List<FileObjects> listOfFileObjects)
	{
		Collections.sort(listOfFileObjects, new Comparator<FileObjects>()
		{
			@Override
			public int compare(FileObjects arg1, FileObjects arg2)
			{
				return arg1.getFileName().compareTo(arg2.getFileName());
			}
		}
				);

	}

	public void sortAscFileTypes(List<FileObjects> listOfFileObjects)
	{
		Collections.sort(listOfFileObjects, new Comparator<FileObjects>()
		{
			@Override
			public int compare(FileObjects arg1, FileObjects arg2)
			{
				return arg1.getFileType().compareTo(arg2.getFileType());
			}
		}
				);

	}

	public void sortAscFilePaths(List<FileObjects> listOfFileObjects)
	{
		Collections.sort(listOfFileObjects, new Comparator<FileObjects>()
		{
			@Override
			public int compare(FileObjects arg1, FileObjects arg2)
			{
				return arg1.getFilePath().compareTo(arg2.getFilePath());
			}
		}
				);

	}
}





package application;

public class FileObjects
{
	private String fileType;
	private String filePath;
	private String fileName;

	public FileObjects(String fp, String fn)
	{
		this.filePath = fp;
		this.fileName = fn;
	}//2 argument constructor, file type is constructed from filename

	public FileObjects(){}//default constructor

	public void setFileType(String fn) 
	{
		this.fileType = getFileType();
	}
	//public String getFileType(){return this.fileType;}

	public String getFileType()
	{
		for (int i = 0; i < this.fileName.length(); i++)
		{
			if (this.fileName.charAt(this.fileName.length() - i - 1) == '.')
			{
				this.fileType = this.fileName.substring(this.fileName.length() - i);
				break;
			}
		}
		return this.fileType.toUpperCase();
	}//finds the first period from the end of the string and cuts it off from there, then returns it as a type

	public void setFilePath(String fp) {this.filePath = fp;}
	public String getFilePath() {return this.filePath;}

	public void setFileName(String fn) {this.fileName = fn;}
	public String getFileName()
	{
		String temp = "";
		for (int i = 0; i < this.fileName.length(); i++)
		{
			if (this.fileName.charAt(this.fileName.length() - i - 1) == '.')
			{
				temp = this.fileName.substring(0, this.fileName.length() - i - 1).substring(0, 1).toUpperCase() + this.fileName.substring(1);
				break;
			}
		}
		return temp;	
	}//returns the filename without the filetype and capitalizes the first letter of the name with the first inner substring, then grabs the last portion of the full string in the second portion

	@Override
	public String toString()
	{
		return getFileType() + "," + getFilePath() + "," + getFileName();
	}//no spaces in between periods to eliminate the need to trim the unnecessary space as a csv

}



Was This Post Helpful? 0
  • +
  • -

#11 macosxnerd101   User is offline

  • Games, Graphs, and Auctions
  • member icon




Reputation: 12769
  • View blog
  • Posts: 45,954
  • Joined: 27-December 08

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 11 July 2020 - 10:15 PM

Since Java has a File class already, you don't need to design your own. If you want to do sorting, just use a List<File> and create a custom Comparator<File> to pass to the Collections.sort() method. It is much cleaner.

By the way, making something public so that the controller will have access to it is usually a sign of bad design. Unless you are talking about constants, there is almost never a good reason to make an instance variable public. Set it to private and restrict access via getters and setters. Do note that if you take my advice from the previous paragraph, your FileObjects class should be deleted. I would also question whether your Functions class is actually necessary.

Your work represents good progress, but you still have a ways to go. :)
Was This Post Helpful? 0
  • +
  • -

#12 g00se   User is offline

  • D.I.C Lover
  • member icon

Reputation: 3704
  • View blog
  • Posts: 16,981
  • Joined: 20-September 08

Re: [JavaFX] Matching indexes of separate ArrayLists after sorting

Posted 12 July 2020 - 04:01 AM

Quote

Since Java has a File class already, you don't need to design your own.

Yes, as i already said above. Never reinvent the wheel. Not only is it a waste of time, but you're also likely to introduce errors that don't exist in the standard library that already does what you need
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1