FileSystem dizinlerinin Bağlantılı Liste uygulaması

Aug 16 2020

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 ... catchbloklar scan()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 ArrayListuygulamanın etrafından dolaşarak üzerinde çalıştığım tek bağlantılı bir listedir . DirEntryYalnızca kendi Pathve bir DirEntry nextnesnesini 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

DanielWiddis Aug 16 2020 at 00:27

Ü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;
        }

       // ...
    }
```