Rumah > Tutorial sistem > LINUX > teks badan

Membandingkan kelebihan dan kekurangan beberapa pelaksanaan carian penghitungan Java yang tidak membuang pengecualian

PHPz
Lepaskan: 2024-01-03 13:24:56
ke hadapan
533 orang telah melayarinya
Pengenalan Java Enum adalah ciri yang sangat berguna, tetapi ramai orang sering tidak memanfaatkannya sepenuhnya kerana sesetengah perpustakaan tidak mengutamakan ciri ini. Biasanya kita juga boleh menggunakan fungsi penghitungan Java dengan betul, tetapi selalunya terdapat masalah sedemikian dalam banyak pangkalan kod, jadi artikel ini ditulis. Persoalannya mudah: bagaimana kita harus mendapatkan enum mengikut nama atau nilai dan mengabaikan nilai yang tidak wujud?
Penghitungan

Ini adalah enum yang akan kami gunakan dalam contoh kami. Penghitungan yang lebih kompleks dipilih supaya penghitungan carian juga boleh diwakili oleh medan lain.

public enum CardColor {
    RED,
    BLACK,
    ;
}
// Jackson annotation to print the enum as an Object instead of the default name.
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum CardSuit {
    // Unicode suits - https://en.wikipedia.org/wiki/Playing_cards_in_Unicode
    SPADE("Spade", String.valueOf((char) 0x2660), CardColor.BLACK),
    HEART("Heart", String.valueOf((char) 0x2665), CardColor.RED),
    DIAMOND("Diamond", String.valueOf((char) 0x2666), CardColor.RED),
    CLUB("Club", String.valueOf((char) 0x2663), CardColor.BLACK),
    ;
    private String displayName;
    private String symbol;
    private CardColor color;
    private CardSuit(String displayName, String symbol, CardColor color) {
        this.displayName = displayName;
        this.symbol =  symbol;
        this.color = color;
    }
    public String getDisplayName() {
        return displayName;
    }
    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }
    public String getSymbol() {
        return symbol;
    }
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    public CardColor getColor() {
        return color;
    }
    public void setColor(CardColor color) {
        this.color = color;
    }
Salin selepas log masuk

Lihat di GitHub.

Soalan

Menggunakan Enum.valueOf sangat bagus apabila anda tahu input itu sah. Walau bagaimanapun, jika nama yang tidak sah dihantar, pengecualian akan dilemparkan. Dalam sesetengah kes, ini tidak mengapa. Secara umum, bagaimanapun, kami lebih suka mengabaikan pengecualian dan mengembalikan nol.

log.debug("Running valueOf");
for (String name : names) {
    try {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.valueOf(name)));
    } catch (Exception ex) {
        log.warn("Exception Thrown", ex);
    }
}
Salin selepas log masuk

2017-02-22 14:46:38.556 [main] DEBUG c.s.examples.common.EnumLookup - Running valueOf
2017-02-22 14:46:38.804 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.808 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
  at java.lang.Enum.valueOf(Enum.java:238)
  at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
  at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:154)
Salin selepas log masuk
Pelaksanaan yang lemah

Malangnya, dua kaedah berikut muncul begitu kerap dalam pangkalan kod. Jangan belajar daripada contoh negatif.

Enum.valueOf Dengan Try Catch (buruk)

Amalan buruk ini paling biasa di kalangan pemula. Pengecualian tidak boleh digunakan untuk aliran kawalan dan mungkin terdapat beberapa kesan prestasi. Jangan malas. Anda perlu melakukannya dengan cara yang betul.

/*
 * Please don't do this! Using try / catch for
 * control flow is a bad practice.
 */
public static CardSuit trycatchValueOf(String name) {
    try {
        return CardSuit.valueOf(name);
    } catch (Exception ex) {
        log.warn("Exception Thrown", ex);
        return null;
    }
}
Salin selepas log masuk

log.debug("Running trycatchValueOf");
for (String name : names) {
    log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.trycatchValueOf(name)));
}
Salin selepas log masuk

2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running trycatchValueOf
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.809 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
  at java.lang.Enum.valueOf(Enum.java:238)
  at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
  at com.stubbornjava.examples.common.EnumLookup$CardSuit.trycatchValueOf(EnumLookup.java:89)
  at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:171)
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Salin selepas log masuk
Cari melalui lelaran (inferior)

Kaedah ini juga sangat biasa (lihat di sini), tetapi sekurang-kurangnya pengaturcara tahu bahawa cuba/tangkap tidak boleh digunakan untuk menangkap pengecualian. Jadi, apa yang salah dengan pendekatan ini? Betul, ia berulang melalui semua penghitungan sehingga ia menemui penghitungan yang sepadan atau mengembalikan null - n kali dalam kes paling teruk, dengan n ialah bilangan nilai penghitungan. Sesetengah mungkin menganggap ini remeh dan hanya pengoptimuman pramatang. Walau bagaimanapun, struktur data dan algoritma adalah asas CS. Ia adalah lebih sukar untuk menggunakan Peta dan bukannya mengulang koleksi. Adakah ini akan meningkatkan prestasi dengan ketara? Tidak, tetapi ia adalah tabiat yang baik untuk dilakukan. Apabila menemu duga calon, adakah anda berasa selesa dengan algoritma carian kerumitan linear? Pada ketika ini, anda tidak seharusnya membiarkan semakan kod sedemikian berlalu.

/*
 * Please don't do this! It is inefficient and it's
 * not very hard to use Guava or a static Map as an index.
 */
public static CardSuit iterationFindByName(String name) {
    for (CardSuit suit : CardSuit.values()) {
        if (name.equals(suit.name())) {
            return suit;
        }
    }
    return null;
}
Salin selepas log masuk

log.debug("Running iteration");
for (String name : names) {
    log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.iterationFindByName(name)));
}
Salin selepas log masuk

2017-02-22 14:46:38.808 [main] DEBUG c.s.examples.common.EnumLookup - Running iteration
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Salin selepas log masuk
Pelaksanaan yang lebih baik

Yang berikut semuanya boleh berfungsi dengan menggunakan indeks dalam bentuk Peta. Walau bagaimanapun, terdapat beberapa perbezaan halus di antara mereka.

Indeks Peta Statik (lebih baik)

Apakah struktur data yang betul untuk carian pantas saiz tetap? Itulah HashMap. Kini dengan beberapa boilerplate tambahan, kami boleh melakukan carian yang lebih cekap dengan syarat kami mempunyai fungsi cincang yang baik. Sedikit lebih bertele-tele, tetapi alangkah baiknya jika ada cara untuk mengurangkan boilerplate.

private static final Map<String, CardSuit> nameIndex =
        Maps.newHashMapWithExpectedSize(CardSuit.values().length);
static {
    for (CardSuit suit : CardSuit.values()) {
        nameIndex.put(suit.name(), suit);
    }
}
public static CardSuit lookupByName(String name) {
    return nameIndex.get(name);
}
Salin selepas log masuk
log.debug("Running lookupByName");
for (String name : names) {
    log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.lookupByName(name)));
}
Salin selepas log masuk
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByName
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Salin selepas log masuk
Guava Enums.getIfPresent (disyorkan)

Ini adalah kes penggunaan biasa dan rakan kami di Google mempunyai penyelesaian yang sangat bersih dan bebas plat dandang untuknya. Melihat ke dalamnya, ia juga menggunakan WeakReferences dan WeakHashMaps. Pada asasnya, kod ini akan mencipta peta statik global yang ditaip dalam nama kelas Enum dan menggunakannya untuk carian.

public static CardSuit getIfPresent(String name) {
    return Enums.getIfPresent(CardSuit.class, name).orNull();
}
Salin selepas log masuk
log.debug("Running Guava getIfPresent");
for (String name : names) {
    log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.getIfPresent(name)));
}
Salin selepas log masuk
2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - Running Guava getIfPresent
2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Salin selepas log masuk
Pengindeksan lanjut mengikut medan

Kaedah yang sama ini boleh digunakan untuk medan lain enum. Ia bukan sesuatu yang luar biasa untuk mencari penghitungan mengikut nama yang dipaparkan atau sifat lain.

Peta Statik diindeks mengikut medan (lebih baik)

Kaedah yang sama seperti di atas, tetapi mengindeks pada nama paparan dan bukannya nama enum.

private static final Map<String, CardSuit> displayNameIndex =
        Maps.newHashMapWithExpectedSize(CardSuit.values().length);
static {
    for (CardSuit suit : CardSuit.values()) {
        displayNameIndex.put(suit.getDisplayName(), suit);
    }
}
public static CardSuit lookupByDisplayName(String name) {
    return displayNameIndex.get(name);
}
Salin selepas log masuk
log.debug("Running lookupByDisplayName");
for (String displayName : displayNames) {
    log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayName(displayName)));
}
Salin selepas log masuk

2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayName
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Salin selepas log masuk
Peta Statik diindeks mengikut medan (lebih baik)

Kami tidak boleh memanfaatkan Jambu Batu di sini kerana sukar untuk mencipta kunci global yang unik untuk indeks statik. Tetapi, itu tidak bermakna kami tidak mempunyai bantuan!

public class EnumUtils {
    public static <T, E extends Enum<E>> Function<T, E> lookupMap(Class<E> clazz, Function<E, T> mapper) {
        @SuppressWarnings("unchecked")
        E[] emptyArray = (E[]) Array.newInstance(clazz, 0);
        return lookupMap(EnumSet.allOf(clazz).toArray(emptyArray), mapper);
    }
    public static <T, E extends Enum<E>> Function<T, E> lookupMap(E[] values, Function<E, T> mapper) {
        Map<T, E> index = Maps.newHashMapWithExpectedSize(values.length);
        for (E value : values) {
            index.put(mapper.apply(value), value);
        }
        return (T key) -> index.get(key);
    }
}
Salin selepas log masuk

Kini kami mempunyai penyelesaian universal yang tidak ada kaitan dengan boilerplate.

private static final Function<String, CardSuit> func =
        EnumUtils.lookupMap(CardSuit.class, e -> e.getDisplayName());
public static CardSuit lookupByDisplayNameUtil(String name) {
    return func.apply(name);
}
Salin selepas log masuk
log.debug("Running lookupByDisplayNameUtil");
for (String displayName : displayNames) {
    log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayNameUtil(displayName)));
}
Salin selepas log masuk
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayNameUtil
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Salin selepas log masuk
Kesimpulan

Terdapat beberapa kaedah di sini yang boleh digunakan untuk menyelesaikan masalah yang sama. Ada yang buruk, ada yang lebih baik.

Teks bahasa Inggeris asal: Java Enum Lookup mengikut Nama atau Medan Tanpa Membuang Pengecualian

Pengarang terjemahan: MaNong.com – Xiaofeng

Atas ialah kandungan terperinci Membandingkan kelebihan dan kekurangan beberapa pelaksanaan carian penghitungan Java yang tidak membuang pengecualian. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:linuxprobe.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!