tl;dr
pathToFile.getParent()
Path#getParent
No need to resort to crude string manipulation. Java NIO abstracts us away from the platform-specific details.
Call Path#getParent to get another path object while dropping the last element of the original.
Path pathToFile = Paths.get( "SomeFolder" , "SomeFile" ) ;
Path pathToFolder = pathToFile.getParent() ;
List#removeLast
By the way, to answer the title of your Question…
In Java 21+, List is a sub-interface of SequencedCollection. This brings convenient new methods such as removeLast.
myList.removeLast() ;
Answer from Basil Bourque on Stack OverflowVideos
tl;dr
pathToFile.getParent()
Path#getParent
No need to resort to crude string manipulation. Java NIO abstracts us away from the platform-specific details.
Call Path#getParent to get another path object while dropping the last element of the original.
Path pathToFile = Paths.get( "SomeFolder" , "SomeFile" ) ;
Path pathToFolder = pathToFile.getParent() ;
List#removeLast
By the way, to answer the title of your Question…
In Java 21+, List is a sub-interface of SequencedCollection. This brings convenient new methods such as removeLast.
myList.removeLast() ;
Actually, you might be getting the UnsupportedOperationException, this is happening because you have used the Arrays.asList method, by using which the list cannot be modified i.e. no elements can be added or removed from the path list.
So, to perform your desired operation, you can use the below code.
String[] pathArray = Paths.get("").toAbsolutePath().toString().split("\\\\");
List<String> path = new ArrayList<>();
Collections.addAll(path, pathArray);
System.out.println(path);
int removeJavaFile = path.size() - 1;
path.remove(removeJavaFile);
System.out.println("Path: "+path);
String filePath = path.stream().map(n -> String.valueOf(n)).collect(Collectors.joining("\\\\"));
System.out.println(filePath);
Here, first you get the pathArray and then add those array elements into a list which can be modified which makes you remove the last element from the list.
We have to keep two pointers previous and current. Since we are keeping a record for the number of elements in the list we can use for loop to traversal the list and find the last node pointed by currentNode pointer and previous node pointed by previousNode pointer. At last, update the previous next pointer to null and return currentNode data.
public E removeLast() {
if(isEmpty()){
throw new NoSuchElementException();
}
Node previousNode = top;
Node currentNode = top;
for (int i = 0; i < numElements -1 ;i++) {
previousNode = currentNode;
currentNode = currentNode.next;
}
// removed the last element and return the data
previousNode.next = null;
numElements--
return currentNode.data;
}
removeFirst and removeLast already exist in the LinkedList class (LinkedList javadoc). No need to create them from scratch then.
See the documentation for ArrayList#remove(int), as in the following syntax:
list.remove(list.size() - 1)
Here is how it's implemented. elementData does a lookup on the backing array (so it can cut it loose from the array), which should be constant time (since the JVM knows the size of an object reference and the number of entries it can calculate the offset), and numMoved is 0 for this case:
public E remove(int index) {
rangeCheck(index); // throws an exception if out of bounds
modCount++; // each time a structural change happens
// used for ConcurrentModificationExceptions
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
Since Java 21, simply using List.removeLast, for example:
List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
System.out.println(list.removeLast()); // 3 - removes and returns the last element
Note: if the list is not empty, the implementation of List.removeLast returns the result of calling remove(size() - 1). Otherwise, it throws NoSuchElementException.
The time complexity of removing the last element from ArrayList is O(1) - it is just decrementing the size of the list by 1 under the hood.
removeLast will throw an NSEE (NoSuchElementException) if the list is empty while pollLast will simply return null if it is empty. Otherwise both will return the item and remove it if the item is present.
Both of these two methods return the last element of the List, but pollLast returns null if the List is empty while removeLast throws a NoSuchElementException in this case.
pollLast documentation:
public E pollLast() Retrieves and removes the last element of this list, or returns null if this list is empty.
removeLast documentation:
public E removeLast() Removes and returns the last element from this list. Throws: NoSuchElementException - if this list is empty