FileSystem dizinlerinin Bağlantılı Liste uygulaması
Bir uç durumu işlemek için Java'da mevcut bir uygulamanın yöntemlerini geçersiz kılan sarmalayıcı sınıfları yazıyorum. Tam uygulama, buraya gönderilmesi gerekenden biraz daha karmaşıktır, bu nedenle yalnızca yardım istediğim bölümleri içeren basitleştirilmiş bir sınıf yazdım.
Sorun Özeti
İki sınıfı genişletiyorum:
Diğer dizinlere sembolik bağlantılar içeren bir dosya sistemindeki bir dizini soyutlayan bir "numaralandırma" sınıfı olarak tasarlanmış bir sınıf. (Gerçek dünya: "/ sys / block".). İki yöntemi vardır scan()
: (bağlantılı) alt dizinlerin listesini oluşturmak için bir yöntem ve listenin getFirst()
ilk öğesini döndürmek için bir yöntem .
İkinci sınıf, birinci sınıf tarafından numaralandırılan işaret edilen dizini soyutlayan bir "giriş" sınıfıdır. Bu iki yöntem, bir sahip getName()
bir dize olarak dizinin yolunu dönmek için yöntem ve getNext()
sonraki öğeye yineleme yöntemi.
Kısıtlamalar
- JDK 8 veya öncesi ile uyumluluk
- Tek iş parçacıklı kullanım varsayılabilir
- Yapıcılar gerektiği gibi değiştirilebilir.
- (En azından) belirtilen iki sınıfı ve her iki yöntemi de uygulamalıdır.
İncelemenin odak noktası
scan()
Yöntem burada mücadelesidir. Çözümü iki şekilde aşırı karmaşıklaştırmış olabileceğimi düşünüyorum:
- Yöntemdeki iç içe geçmiş
try ... catch
bloklarscan()
olağandışı görünüyor. Bunu halletmenin daha basit bir yolunu mu kaçırıyorum? - (GÜNCELLEME: Aşağıdaki bu ikinci soruyu kendi kendime cevapladı.) Uygulanan model, açıkça bir
ArrayList
uygulamanın etrafından dolaşarak üzerinde çalıştığım tek bağlantılı bir listedir .DirEntry
Yalnızca kendiPath
ve birDirEntry next
nesnesini içeren sınıfı hayal edebiliyorum , ancak böyle bir liste oluşturma girişimleri, oluşturduğum geçici çözümden daha karmaşık veya daha az performanslı görünüyor.
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DeviceList {
/**
* Class representing a parent directory which contains symbolic links to other
* directories
*/
static class DirEnumerator {
private Path dirPath;
private List<DirEntry> entryList = Collections.emptyList();
public DirEnumerator(String path) {
dirPath = FileSystems.getDefault().getPath(path);
}
/**
* Scans the directory for entries
*
* @return The number of entries found
*/
public int scan() {
try (Stream<Path> paths = Files.walk(dirPath)) {
List<Path> linkedDirs = paths.filter(Files::isSymbolicLink).map(p -> {
try {
return Files.readSymbolicLink(p);
} catch (IOException e) {
return p;
}
}).collect(Collectors.toList());
this.entryList = new ArrayList<>();
for (int i = 0; i < linkedDirs.size(); i++) {
this.entryList.add(new DirEntry(entryList, linkedDirs.get(i), i));
}
return this.entryList.size();
} catch (IOException e) {
this.entryList = Collections.emptyList();
return 0;
}
}
/**
* Gets the first entry in the scanned list
*
* @return The first entry if it exists; null otherwise
*/
public DirEntry getFirst() {
return entryList.isEmpty() ? null : entryList.get(0);
}
}
/**
* Class representing a directory
*/
static class DirEntry {
private List<DirEntry> entryList;
private Path path;
private int index;
public DirEntry(List<DirEntry> entryList, Path path, int i) {
this.entryList = entryList;
this.path = path;
this.index = i;
}
/**
* Gets the path name of the directory entry
*
* @return a string representing the path
*/
public String getName() {
return this.path.toString();
}
/**
* Gets the next entry in the list
*
* @return the next entry if it exists; null otherwise
*/
public DirEntry getNext() {
int nextIndex = index + 1;
return nextIndex < entryList.size() ? entryList.get(nextIndex) : null;
}
}
public static void main(String[] args) {
// Test on any directory containing symbolic links to other directories
DirEnumerator de = new DirEnumerator("/sys/block");
int n = de.scan();
System.out.println("Found " + n + " directories.");
DirEntry e = de.getFirst();
while (e != null) {
System.out.println("Directory: " + e.getName());
e = e.getNext();
}
}
}
```
Yanıtlar
Üretilen yollardan geriye doğru yineleyerek Bağlantılı Liste oluşturarak, ikinci soruyu yapmanın daha basit bir yolunu buldum.
static class DirEnumerator {
private Path dirPath;
private DirEntry first = null;
// ...
public int scan() {
try (Stream<Path> paths = Files.walk(dirPath)) {
List<Path> linkedDirs = paths.filter(Files::isSymbolicLink).map(p -> {
try {
return Files.readSymbolicLink(p);
} catch (IOException e) {
return p;
}
}).collect(Collectors.toList());
this.first = null;
int i = linkedDirs.size();
while (i-- > 0) {
this.first = new DirEntry(linkedDirs.get(i), first);
}
return linkedDirs.size();
} catch (IOException e) {
this.first = null;
return 0;
}
}
// ...
}
static class DirEntry {
private Path path;
private DirEntry next;
public DirEntry(Path path, DirEntry next) {
this.path = path;
this.next = next;
}
// ...
}
```