รูปแบบการใช้งานของ Java 8's Optional.ifPresent และ if-not-Present?


274

ใน Java 8 ฉันต้องการทำบางสิ่งกับOptionalวัตถุถ้ามีอยู่และทำสิ่งอื่นหากไม่มีอยู่

if (opt.isPresent()) {
  System.out.println("found");
} else {
  System.out.println("Not found");
}

แม้ว่านี่จะไม่ใช่ 'สไตล์การทำงาน' ก็ตาม

OptionalมีifPresent()วิธีการ แต่ฉันไม่สามารถเชื่อมโยงorElse()วิธีการใด ๆ

ดังนั้นฉันไม่สามารถเขียน:

opt.ifPresent( x -> System.out.println("found " + x))
   .orElse( System.out.println("NOT FOUND"));

ในการตอบกลับถึง @assylias ฉันไม่คิดว่าจะOptional.map()ทำงานได้ในกรณีต่อไปนี้:

opt.map( o -> {
  System.out.println("while opt is present...");
  o.setProperty(xxx);
  dao.update(o);
  return null;
}).orElseGet( () -> {
  System.out.println("create new obj");
  dao.save(new obj);
  return null;
});

ในกรณีนี้เมื่อoptมีอยู่ฉันอัพเดตคุณสมบัติและบันทึกลงในฐานข้อมูล เมื่อไม่พร้อมฉันสร้างใหม่objและบันทึกลงในฐานข้อมูล

หมายเหตุในสอง lambdas nullฉันต้องกลับมา

แต่เมื่อoptมีอยู่แกะทั้งสองจะถูกประหารชีวิต objจะได้รับการปรับปรุงและวัตถุใหม่จะถูกบันทึกลงในฐานข้อมูล นี่เป็นเพราะreturn nullแลมบ์ดาในครั้งแรก และorElseGet()จะดำเนินการต่อไป


53
ใช้ตัวอย่างแรกของคุณ มันเป็นความสวยงาม
Sotirios Delimanolis

3
ฉันขอแนะนำให้คุณหยุดบังคับพฤติกรรมบางอย่างเมื่อใช้ API ที่ไม่ได้ออกแบบมาสำหรับการทำงานนั้น ตัวอย่าง rfirst คุณดูดีสำหรับฉันนอกเหนือจากคำพูดสไตล์เล็ก ๆ บางอย่าง แต่สิ่งเหล่านี้เป็น opiniated
skiwi

4
@smallufo: แทนที่return null;ด้วยreturn o;(ทั้งคู่) อย่างไรก็ตามฉันมีความรู้สึกที่แข็งแกร่งว่าคุณกำลังทำงานผิดที่ คุณควรทำงานที่ไซต์ที่ผลิตออกOptionalมา Optionalในสถานที่ที่ว่าควรจะมีวิธีการที่จะดำเนินการตามที่ต้องการโดยไม่ต้องระดับกลาง
Holger

10
Java 9 ใช้วิธีแก้ปัญหาของคุณ: iteratrlearning.com/java9/2016/09/05/java9-optional.html
pisaruk

2
ฉันคิดว่าเหตุผลที่สิ่งนี้ไม่สามารถทำได้อย่างง่ายดายนั้นมีวัตถุประสงค์ ทางเลือกไม่ควรทำการควบคุมการไหล แต่เป็นการแปลงค่า ฉันรู้ว่าสิ่งifPresentนี้ขัดแย้ง วิธีการอื่น ๆ ทั้งหมดอ้างถึงคุณค่าและไม่ใช่การกระทำ
AlikElzin-kilaka

คำตอบ:


109

สำหรับฉันคำตอบของ @Dane White ก็โอเคก่อนอื่นฉันไม่ชอบใช้ Runnable แต่ฉันไม่สามารถหาทางเลือกอื่น ๆ ได้นี่เป็นอีกวิธีที่ฉันต้องการมากกว่า

public class OptionalConsumer<T> {
    private Optional<T> optional;

    private OptionalConsumer(Optional<T> optional) {
        this.optional = optional;
    }

    public static <T> OptionalConsumer<T> of(Optional<T> optional) {
        return new OptionalConsumer<>(optional);
    }

    public OptionalConsumer<T> ifPresent(Consumer<T> c) {
        optional.ifPresent(c);
        return this;
    }

    public OptionalConsumer<T> ifNotPresent(Runnable r) {
        if (!optional.isPresent()) {
            r.run();
        }
        return this;
    }
}

จากนั้น:

Optional<Any> o = Optional.of(...);
OptionalConsumer.of(o).ifPresent(s ->System.out.println("isPresent "+s))
            .ifNotPresent(() -> System.out.println("! isPresent"));

อัปเดต 1:

วิธีการแก้ปัญหาข้างต้นสำหรับวิธีการพัฒนาแบบดั้งเดิมเมื่อคุณมีค่าและต้องการประมวลผล แต่ถ้าฉันต้องการกำหนดฟังก์ชั่นการใช้งานและการดำเนินการจะเป็นเช่นนั้นตรวจสอบการปรับปรุงด้านล่าง;

public class OptionalConsumer<T> implements Consumer<Optional<T>> {
private final Consumer<T> c;
private final Runnable r;

public OptionalConsumer(Consumer<T> c, Runnable r) {
    super();
    this.c = c;
    this.r = r;
}

public static <T> OptionalConsumer<T> of(Consumer<T> c, Runnable r) {
    return new OptionalConsumer(c, r);
}

@Override
public void accept(Optional<T> t) {
    if (t.isPresent()) {
        c.accept(t.get());
    }
    else {
        r.run();
    }
}

จากนั้นสามารถใช้เป็น:

    Consumer<Optional<Integer>> c=OptionalConsumer.of(System.out::println, ()->{System.out.println("Not fit");});
    IntStream.range(0, 100).boxed().map(i->Optional.of(i).filter(j->j%2==0)).forEach(c);

ในรหัสใหม่นี้คุณมี 3 สิ่ง:

  1. สามารถกำหนดฟังก์ชั่นก่อนวัตถุที่มีอยู่ได้ง่าย
  2. ไม่ได้สร้างการอ้างอิงวัตถุสำหรับตัวเลือกแต่ละตัวเพียงตัวเดียวคุณมีหน่วยความจำน้อยกว่าและ GC น้อยลง
  3. เป็นการใช้งานของผู้บริโภคเพื่อการใช้งานที่ดีขึ้นกับส่วนประกอบอื่น

ตอนนี้ชื่อของมันมีความหมายมากกว่าจริง ๆ แล้วมันคือ Consumer>


3
ควรใช้ตัวเลือก
Option.Nullable

2
คุณจำเป็นต้องใช้ค่า Nullable ถ้าคุณไม่แน่ใจว่าค่าที่คุณจะใช้มีค่าเป็น null หรือไม่และไม่จำเป็นต้องเผชิญกับ NPE และในกรณีที่คุณแน่ใจว่าไม่เป็นค่า Null หรือคุณไม่สนใจว่าจะได้รับ NPE
Bassem Reda Zohdy

1
ฉันคิดว่าคลาส OptionalConsumer นั้นดูดีกว่าถ้า / ในรหัส ขอบคุณ! :)
witek1902

207

หากคุณใช้ Java 9+ คุณสามารถใช้ifPresentOrElse()วิธีการ:

opt.ifPresentOrElse(
   value -> System.out.println("Found: " + value),
   () -> System.out.println("Not found")
);

3
ดีเพราะมันเกือบจะสะอาดพอ ๆ กับการจับคู่รูปแบบใน Scala
sscarduzio

แลมบ์ดาสองแบบนั้นน่าเกลียดทีเดียว ฉันคิดว่าถ้า / อื่นสะอาดกว่าสำหรับกรณีเหล่านี้
john16384

1
@ john16384 ตกลงถ้าคุณพบว่ามันน่าเกลียดแล้วฉันจะลบคำตอบของฉัน (ไม่)
ZhekaKozlov

นี่เป็นสิ่งที่ดีมาก แต่คำถามนี้มีขึ้นสำหรับ JDK8 โดยเฉพาะเพราะ ifPresentOrElse ไม่พร้อมใช้งาน
hreinn

81

Java 9 แนะนำ

ifPresentOrElse หากมีค่าอยู่ให้ดำเนินการตามที่กำหนดด้วยค่าหรือดำเนินการตามที่ว่างเปล่า

ดูที่ยอดเยี่ยมเป็นตัวเลือกในชวา 8 แผ่นโกง

มันมีคำตอบทั้งหมดสำหรับกรณีการใช้งานมากที่สุด

สรุปสั้น ๆ ด้านล่าง

ifPresent () - ทำบางสิ่งเมื่อตั้งค่าตัวเลือก

opt.ifPresent(x -> print(x)); 
opt.ifPresent(this::print);

ตัวกรอง () - ปฏิเสธ (กรอง) ค่าตัวเลือกบางอย่าง

opt.filter(x -> x.contains("ab")).ifPresent(this::print);

map () - แปลงค่าถ้ามี

opt.map(String::trim).filter(t -> t.length() > 1).ifPresent(this::print);

orElse () / orElseGet () - การเปิดว่างเปล่าตัวเลือกเพื่อ T เริ่มต้น

int len = opt.map(String::length).orElse(-1);
int len = opt.
    map(String::length).
    orElseGet(() -> slowDefault());     //orElseGet(this::slowDefault)

orElseThrow () - โยนข้อยกเว้นอย่างเกียจคร้านบนตัวเลือกที่ว่างเปล่า

opt.
filter(s -> !s.isEmpty()).
map(s -> s.charAt(0)).
orElseThrow(IllegalArgumentException::new);

66
นี่ไม่ได้ตอบคำถามของ OP จริง ๆ มันตอบสนองการใช้งานทั่วไป แต่ไม่ใช่สิ่งที่ OP ขอ
Captain Man

1
@CaptainMan จริง ๆ แล้วมันทำ; การแสดงออก opt.map ("พบ") หรือการแสดงออก ("ไม่พบ") ​​เติมบิล
Matt

4
@ ตัวเลขไม่ OP จะขอการกระทำโดยเฉพาะเมื่อตัวเลือกเป็น / ไม่มีอยู่จะไม่ส่งคืนค่าเมื่อเป็นหรือไม่ OP ยังกล่าวถึงสิ่งที่คล้ายกันในคำถามโดยใช้ orElseGet อธิบายว่าทำไมมันไม่ทำงาน
Captain Man

2
@ กัปตันแมนฉันเห็นประเด็นของคุณ ฉันคิดว่าเขาสามารถทำให้มันทำงานได้ถ้าเขาไม่คืนค่าว่างจากmapมัน แต่มันค่อนข้างแปลกที่จะถามหาฟังก์ชั่นการใช้งานเพื่อที่คุณจะได้เรียก DAO ดูเหมือนว่าฉันจะเหมาะสมกว่าที่จะคืนค่าวัตถุที่ได้รับการอัพเดต / ใหม่จากmap.orElseบล็อกนี้จากนั้นทำสิ่งที่คุณต้องทำกับวัตถุที่ส่งคืน
Matt

1
ฉันคิดว่าmapให้ความสำคัญกับกระแสและไม่ได้มีไว้สำหรับ "ทำสิ่งต่าง ๆ กับวัตถุอื่นขึ้นอยู่กับสถานะขององค์ประกอบนี้ในกระแส" เป็นการดีที่จะรู้ว่าifPresentOrElseมีการเพิ่มใน Java 9
WesternGun

53

ทางเลือกคือ:

System.out.println(opt.map(o -> "Found")
                      .orElse("Not found"));

ฉันไม่คิดว่ามันช่วยให้อ่านง่ายขึ้น

หรือตามที่แนะนำจาก Marko ให้ใช้ตัวดำเนินการที่ประกอบไปด้วย:

System.out.println(opt.isPresent() ? "Found" : "Not found");

2
ขอบคุณ @assylias แต่ฉันไม่คิดว่า Option.map () จะเหมาะกับกรณีและปัญหา (ดูการอัปเดตบริบทของฉัน)
smallufo

2
@smallufo คุณจะต้องกลับมาnew Object();ในแลมบ์ด้าแรกของคุณ แต่บอกตามตรงว่ามันน่าเกลียดมาก ฉันจะใช้ if / else สำหรับตัวอย่างที่อัปเดตของคุณ
assylias

เห็นด้วยโดยใช้mapเพียงแค่ผลตอบแทนOptionalสำหรับการผูกมัดทำให้รหัสที่ยากที่จะเข้าใจในขณะที่mapจะถือว่าแท้จริง map บางสิ่งบางอย่าง
Tiina

40

อีกวิธีคือการใช้ฟังก์ชั่นที่มีลำดับสูงกว่าดังต่อไปนี้

opt.<Runnable>map(value -> () -> System.out.println("Found " + value))
   .orElse(() -> System.out.println("Not Found"))
   .run();

8
ในสายตาของฉันทางออกที่ดีที่สุดโดยไม่ต้อง JDK 9
Semaphor

5
คำอธิบายจะดีมาก ฉันถามตัวเองว่าทำไมคุณต้องใช้แผนที่ runnable (?) และความvalue -> () -> sysoหมายของส่วนนั้น
froehli

ขอบคุณสำหรับโซลูชันนี้! ฉันคิดว่าเหตุผลในการใช้ Runnable คือว่าแผนที่ที่ออกไม่ส่งคืนค่าใด ๆ และด้วย Runnable จะส่งคืนแลมบ์ดาและเช่นผลลัพธ์ของแผนที่คือแลมบ์ดาที่เราเรียกใช้หลังจากนั้น ดังนั้นหากคุณมีค่าที่ส่งคืนคุณสามารถใช้สิ่งต่อไปนี้:String result = opt.map(value -> "withOptional").orElse("without optional");
nanotexnik

21

ไม่มีวิธีที่ยอดเยี่ยมที่จะทำมันออกมาจากกล่อง หากคุณต้องการใช้ไวยากรณ์ตัวล้างของคุณเป็นประจำคุณสามารถสร้างคลาสยูทิลิตี้เพื่อช่วยได้:

public class OptionalEx {
    private boolean isPresent;

    private OptionalEx(boolean isPresent) {
        this.isPresent = isPresent;
    }

    public void orElse(Runnable runner) {
        if (!isPresent) {
            runner.run();
        }
    }

    public static <T> OptionalEx ifPresent(Optional<T> opt, Consumer<? super T> consumer) {
        if (opt.isPresent()) {
            consumer.accept(opt.get());
            return new OptionalEx(true);
        }
        return new OptionalEx(false);
    }
}

จากนั้นคุณสามารถใช้การนำเข้าแบบคงที่ที่อื่นเพื่อรับไวยากรณ์ที่ใกล้เคียงกับสิ่งที่คุณทำหลังจาก:

import static com.example.OptionalEx.ifPresent;

ifPresent(opt, x -> System.out.println("found " + x))
    .orElse(() -> System.out.println("NOT FOUND"));

ขอบคุณ วิธีนี้มีความสวยงาม ฉันรู้ว่าอาจไม่มีวิธีแก้ปัญหาในตัว (ยกเว้นว่า JDK รวมวิธีการดังกล่าว) คุณก็ได้ ExEx มีประโยชน์มาก ยังไงก็ขอบคุณนะ.
smallufo

ใช่ฉันชอบผลลัพธ์และสไตล์ที่รองรับ ดังนั้นทำไมไม่ใช้ API มาตรฐาน
guthrie

คำตอบที่ดี. เราทำเช่นเดียวกัน ผมเห็นว่ามันควรจะอยู่ใน API แต่จะได้รับลดลง (หรือภาษา!): bugs.openjdk.java.net/browse/JDK-8057557
Garrett Smith

ดี นี่ควรเป็นส่วนหนึ่งของ JDK 8.1 เพื่อประกอบการพิจารณา
peter_pilgrim

35
Optional.ifPresentOrElse()ได้รับการเพิ่มใน JDK 9
Stuart Marks

9

หากคุณสามารถใช้เฉพาะ Java 8 หรือต่ำกว่า:

1) หากคุณไม่มีspring-dataวิธีที่ดีที่สุด:

opt.<Runnable>map(param -> () -> System.out.println(param))
      .orElse(() -> System.out.println("no-param-specified"))
      .run();

ตอนนี้ฉันรู้ว่ามันไม่สามารถอ่านได้และยากที่จะเข้าใจสำหรับใครบางคน แต่ดูดีสำหรับฉันเป็นการส่วนตัวและฉันไม่เห็นวิธีที่ดีอีกอย่างสำหรับกรณีนี้

2) ถ้าคุณโชคดีพอและคุณสามารถใช้spring-dataวิธีที่ดีที่สุดคือ Optionals # ifPresentOrElse :

Optionals.ifPresentOrElse(opt, System.out::println,
      () -> System.out.println("no-param-specified"));

หากคุณสามารถใช้ Java 9 คุณควรไปกับ:

opt.ifPresentOrElse(System.out::println,
      () -> System.out.println("no-param-specified"));

2

พฤติกรรมที่อธิบายสามารถทำได้โดยใช้Vavr (เดิมชื่อ Javaslang) ซึ่งเป็น object-functional library สำหรับ Java 8+ ซึ่งใช้ Scala constructs ส่วนใหญ่ เป็นห้องสมุดที่ดีมากในการเพิ่มโปรเจ็กต์ Java ของคุณเพื่อเขียนโค้ดการทำงานที่แท้จริง

Vavr จัดเตรียมOptionmonad ที่จัดเตรียมฟังก์ชันเพื่อทำงานกับชนิด Option เช่น:

  • fold: เพื่อแมปค่าของตัวเลือกในทั้งสองกรณี (กำหนด / ว่าง)
  • onEmpty: อนุญาตให้ดำเนินการRunnableตัวเลือกเมื่อว่างเปล่า
  • peek: อนุญาตให้ใช้ค่าของตัวเลือก (เมื่อกำหนด)
  • และมันก็เป็นSerializableสิ่งที่ตรงกันข้ามOptionalซึ่งหมายความว่าคุณสามารถใช้มันได้อย่างปลอดภัยเป็นอาร์กิวเมนต์ของเมธอดและสมาชิกอินสแตนซ์

ตัวเลือกเป็นไปตามกฎหมาย monad ที่แตกต่างจาก "pseudo-monad" ของ Java และให้ API ที่สมบูรณ์ยิ่งขึ้น และแน่นอนว่าคุณสามารถทำได้จากทางเลือกของ Java (และวิธีอื่น ๆ ): Option.ofOptional(javaOptional)–Vavr มุ่งเน้นที่การทำงานร่วมกัน

ไปที่ตัวอย่าง:

// AWESOME Vavr functional collections (immutable for the gread good :)
// fully convertible to Java's counterparts.
final Map<String, String> map = Map("key1", "value1", "key2", "value2");

final Option<String> opt = map.get("nonExistentKey"); // you're safe of null refs!

final String result = opt.fold(
        () -> "Not found!!!",                // Option is None
        val -> "Found the value: " + val     // Option is Some(val)
);

อ่านเพิ่มเติม

การอ้างอิงเป็นศูนย์ความผิดพลาดพันล้านดอลลาร์

NBนี่เป็นเพียงตัวอย่างเล็ก ๆ น้อย ๆ ของสิ่งที่ Vavr เสนอ (การจับคู่รูปแบบ, สตรีมหรือรายการที่ประเมินที่ขี้เกียจ, ประเภท monadic, คอลเลกชันที่ไม่เปลี่ยนรูป, ... )


1

โซลูชันอื่นอาจตามมา:

นี่คือวิธีที่คุณใช้:

    final Opt<String> opt = Opt.of("I'm a cool text");
    opt.ifPresent()
        .apply(s -> System.out.printf("Text is: %s\n", s))
        .elseApply(() -> System.out.println("no text available"));

หรือในกรณีที่คุณใช้ในกรณีตรงข้ามกับการใช้งานจริง:

    final Opt<String> opt = Opt.of("This is the text");
    opt.ifNotPresent()
        .apply(() -> System.out.println("Not present"))
        .elseApply(t -> /*do something here*/);

นี่คือส่วนผสม:

  1. ส่วนต่อประสานฟังก์ชั่นการปรับเปลี่ยนเล็กน้อยสำหรับวิธี "elseApply"
  2. ตัวเลือกเสริม
  3. กระแสเล็กน้อย :-)

อินเทอร์เฟซฟังก์ชั่นที่เพิ่มประสิทธิภาพ

@FunctionalInterface
public interface Fkt<T, R> extends Function<T, R> {

    default R elseApply(final T t) {
        return this.apply(t);
    }

}

และคลาส wrapper เผื่อเลือกสำหรับการปรับปรุง:

public class Opt<T> {

    private final Optional<T> optional;

    private Opt(final Optional<T> theOptional) {
        this.optional = theOptional;
    }

    public static <T> Opt<T> of(final T value) {
        return new Opt<>(Optional.of(value));
    }

    public static <T> Opt<T> of(final Optional<T> optional) {
        return new Opt<>(optional);
    }

    public static <T> Opt<T> ofNullable(final T value) {
        return new Opt<>(Optional.ofNullable(value));
    }

    public static <T> Opt<T> empty() {
        return new Opt<>(Optional.empty());
    }

    private final BiFunction<Consumer<T>, Runnable, Void> ifPresent = (present, notPresent) -> {
        if (this.optional.isPresent()) {
            present.accept(this.optional.get());
        } else {
            notPresent.run();
        }
        return null;
    };

   private final BiFunction<Runnable, Consumer<T>, Void> ifNotPresent = (notPresent, present) -> {
        if (!this.optional.isPresent()) {
            notPresent.run();
        } else {
            present.accept(this.optional.get());
        }
        return null;
    };

    public Fkt<Consumer<T>, Fkt<Runnable, Void>> ifPresent() {
        return Opt.curry(this.ifPresent);
    }

    public Fkt<Runnable, Fkt<Consumer<T>, Void>> ifNotPresent() {
        return Opt.curry(this.ifNotPresent);
    }

    private static <X, Y, Z> Fkt<X, Fkt<Y, Z>> curry(final BiFunction<X, Y, Z> function) {
        return (final X x) -> (final Y y) -> function.apply(x, y);
    }
}

สิ่งนี้ควรทำเคล็ดลับและสามารถใช้เป็นแม่แบบพื้นฐานวิธีจัดการกับข้อกำหนดดังกล่าว

แนวคิดพื้นฐานที่นี่มีดังต่อไปนี้ ในโลกของการเขียนโปรแกรมแบบไม่ทำงานคุณอาจใช้วิธีการรับพารามิเตอร์สองตัวโดยที่ตัวแรกเป็นรหัสที่สามารถรันได้ในกรณีที่มีค่าและอีกพารามิเตอร์คือรหัสที่เรียกใช้ซึ่งควรจะรันในกรณีที่ ค่าไม่พร้อมใช้งาน เพื่อประโยชน์ในการอ่านที่ดีขึ้นคุณสามารถใช้กระแสเพื่อแยกฟังก์ชั่นของพารามิเตอร์สองตัวในสองฟังก์ชั่นของหนึ่งพารามิเตอร์แต่ละตัว นี่คือสิ่งที่ฉันทำโดยทั่วไปที่นี่

คำแนะนำ: การเลือกใช้ยังมีเคสการใช้งานอื่นที่คุณต้องการเรียกใช้งานโค้ดในกรณีที่ค่าไม่พร้อมใช้งาน สิ่งนี้สามารถทำได้ผ่านทาง Optional.filter.stuff แต่ฉันพบสิ่งนี้อ่านได้มากขึ้น

หวังว่าจะช่วย!

การเขียนโปรแกรมที่ดี :-)


คุณบอกได้ไหมว่าอะไรไม่ทำงาน ฉันทดสอบอีกครั้งและสำหรับฉันมันใช้งานได้?
Alessandro Giusa

ขอโทษนะ แต่ ckass Fkt ถูกกำหนดไว้ที่ไหน? สุดท้าย แต่ไม่
ท้ายสุด

Fkt ถูกกำหนดไว้ด้านบนเป็นส่วนต่อประสาน เพียงอ่านบทความทั้งหมด :-)
Alessandro Giusa

ใช่. ฉันเปลี่ยนส่วนต่อประสาน EFunction เป็น Fkt เป็นชื่อ มีการพิมพ์ผิด ขอบคุณสำหรับการตรวจสอบ :-) ขออภัยสำหรับสิ่งนั้น
Alessandro Giusa

ฉันไม่คิดว่าเป็นความคิดที่ดีที่จะเขียนโค้ดแบบนี้ ... คุณควรใช้ยูทิลิตี้ jdk เมื่อคุณสามารถ
Tyulpan Tyulpan

0

ในกรณีที่คุณต้องการเก็บค่า:

Pair.of<List<>, List<>> output = opt.map(details -> Pair.of(details.a, details.b))).orElseGet(() -> Pair.of(Collections.emptyList(), Collections.emptyList()));

0

สมมติว่าคุณมีรายการและหลีกเลี่ยงisPresent()ปัญหา (เกี่ยวข้องกับตัวเลือก) คุณสามารถใช้.iterator().hasNext()เพื่อตรวจสอบว่าไม่มี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.