Bagaimana cara tidak menambahkan nilai nol ke LoadingCache Guava?

Saya harus menggunakan LoadingCache Guava untuk menyimpan ekspresi xpath ke nilai xpath.

Masalahnya adalah tidak semua xpath memiliki nilai. Seringkali nilainya adalah null.

Cuplikan kode:

private LoadingCache<String, List<String>> cachedXpaths = CacheBuilder.newBuilder()
        .expireAfterWrite(3, TimeUnit.MINUTES)
        .maximumSize(1000)
        .concurrencyLevel(5)
        .weakKeys()
        .build(new CacheLoader<String, List<String>>() {
            @Override
            public List<String> load(String key) throws Exception {
                return createListByKey(key);
            }
        });

private static List<String> createListByKey(String key) throws Exception {
    List<String> values = null;
    try {
        values = instance.getXpathValues(key);
    } catch (XPathExpressionException ignore) {
    }
    return values;
}

Hasil:

testEncounterSection(com.epam.cdatest.section.EncountersSectionTest)  Time elapsed: 0.002 sec  <<< FAILURE!
com.google.common.util.concurrent.UncheckedExecutionException: com.epam.cdatest.exceptions.XpathHasEmptyValueException
    at com.epam.cdatest.parsers.XpathEvaluator.getXpathValues(XpathEvaluator.java:123)
    at com.epam.cdatest.parsers.XpathEvaluator.createListByKey(XpathEvaluator.java:53)
    at com.epam.cdatest.parsers.XpathEvaluator.access$000(XpathEvaluator.java:32)
    at com.epam.cdatest.parsers.XpathEvaluator$1.load(XpathEvaluator.java:46)
    at com.epam.cdatest.parsers.XpathEvaluator$1.load(XpathEvaluator.java:43)

Bagaimana cara menghindari panggilan load() ketika nilai xpath kosong?


person catch23    schedule 16.06.2015    source sumber
comment
Mengapa Anda ingin menghindari panggilan ke load() daripada hanya mengembalikan daftar kosong? Faktanya, cache tidak dapat mengetahui kunci mana yang tidak diperbolehkan dan karenanya akan mencoba memuat setidaknya sekali. Pemuat kemudian harus memutuskan apa yang harus dilakukan dengan kunci tersebut.   -  person Thomas    schedule 16.06.2015
comment
@Thomas bagaimana cara melewati daftar kosong ini kembali? atau bagaimana cara menyetel cache untuk menghapus daftar kosong terlebih dahulu?   -  person catch23    schedule 16.06.2015
comment
Itu tidak melewatkan panggilan return values tetapi setelah itu cache tidak akan memuat nilai untuk kunci yang diberikan lagi dan akan selalu mengembalikan daftar kosong itu, yang menunjukkan bahwa tidak ada nilai xpath untuk kunci itu.   -  person Thomas    schedule 16.06.2015
comment
Kecuali Anda benar-benar perlu membedakan antara ilegal dan tidak ada apa pun di sana, saya sarankan untuk mengembalikan daftar kosong dalam kedua kasus.   -  person maaartinus    schedule 16.06.2015
comment
@maaartinus Saya ingin tahu efisiensi cache ini jika nilai List‹String› kosong. Apakah cache ini menghapusnya lebih jauh dibandingkan dengan daftar yang memiliki beberapa nilai? Bisakah Anda menjelaskan lebih lanjut tentang ini?   -  person catch23    schedule 16.06.2015
comment
@nazar_art Ini akan menanganinya dengan cara yang persis sama seperti nilai-nilai lainnya, yang mungkin sesuai atau tidak Anda inginkan. Namun menurut saya, ini adalah hal yang benar, karena jalur ilegal mungkin memerlukan waktu pemrosesan yang hampir sama dengan jalur legal (ukurlah jika Anda benar-benar peduli).   -  person maaartinus    schedule 16.06.2015


Jawaban (1)


Jika Anda ingin membedakan antara List<String> yang kosong dan yang null, karena LoadingCache tidak mendukung null, Anda dapat menggunakan LoadingCache<String, Optional<List<String>>>:

private LoadingCache<String, Optional<List<String>>> cachedXpaths = CacheBuilder.newBuilder()
        .expireAfterWrite(3, TimeUnit.MINUTES)
        .maximumSize(1000)
        .concurrencyLevel(5)
        .weakKeys()
        .build(new CacheLoader<String, Optional<List<String>>>() {
            @Override
            public Optional<List<String>> load(String key) {
                try {
                    // If getXpathValues() can also return null, use fromNullable()
                    return Optional.of(instance.getXpathValues(key));
                } catch (XPathExpressionException | XpathHasEmptyValueException ignore) {
                    // Maybe log something here as well
                    return Optional.absent();
                }
            }
        });

Pembaruan: jika Anda tidak terbiasa dengan Optional, ada Javadoc, halaman di rel Wiki, serta semua dokumentasi untuk Java 8 yang kini menyertakan kelas setara.

TL;DR itu adalah pembungkus yang dapat diuji keberadaan isinya:

Optional<List<String>> optionalXpaths = cachedXpaths.getUnchecked(str);
if (optionalXpaths.isPresent()) {
    List<String> xpaths = optionalXpaths.get();
    // Do something with xpaths
}

atau sebagai alternatif (tapi lebih jelek):

List<String> xpaths = cachedXpaths.getUnchecked(str).orNull();
if (xpaths != null) {
    // Do something with xpaths
}
person Frank Pavageau    schedule 16.06.2015