亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

是否可以編寫一個循環訪問集合和數組的 for 循環?

是否可以編寫一個循環訪問集合和數組的 for 循環?

慕的地6264312 2022-09-28 16:11:59
是否可以檢查對象是數組還是具有一個子句的集合?我試圖實現的目標:假設數組實現了 Iterable,并且假設 Object 可以是數組或集合,我想使用這樣的代碼片段:fooif (foo instanceof Iterable) {  for (Object f : (Iterable) foo) {    // do something with f  }}遺憾的是,數組不能轉換為可迭代。它也不實現收集。是否有其他可能性可以像上面這樣在一個循環中處理兩者?而不是 - 當然 - 使用一個 if-else if 子句和兩個循環(這不好)。編輯:回應這些答案。我知道 isArray() 方法,但在這種情況下,轉換在...for (Object f : (Iterable) foo) {...將失敗。這很可惜,也是代碼冗余,因為我必須使用兩個循環,盡管foreach循環同時適用于集合和數組。
查看完整描述

5 回答

?
一只名叫tom的貓

TA貢獻1906條經驗 獲得超3個贊

關于檢查 foo 是集合還是數組的條件:

類#是可分配的可能派上用場。

Class<?> fooClass = foo.getClass();

boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||

                              Object[].class.isAssignableFrom(fooClass);

我合理地假設你不會在基元數組上測試它,因為你有只使用包裝類的集合。


我想你可以安全地替換為Object[].class.isAssignableFrom(fooClass)fooClass.isArray()


boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||

                              fooClass.isArray();

它也適用于基元數組類。


我運行了一個小的“測試”


class Test {

    public static void main(String[] args) {

        Predicate<Class<?>> p = c -> Collection.class.isAssignableFrom(c) || 

                                     c.isArray();


        System.out.println(p.test(new int[0].getClass()));

        System.out.println(p.test(new Integer[0].getClass()));

        System.out.println(p.test(Collections.emptyList().getClass()));

        System.out.println(p.test(Collections.emptySet().getClass()));


        System.out.println(p.test(Collections.emptyMap().getClass()));

    }

}

這導致


true

true

true

true

false

關于將同時在數組和集合上運行的泛型循環:


你根本無法寫一個準確的構造來處理這個問題:(或)并且幾乎沒有共同點(因為一個共同的父級及其方法是不夠的)。CollectionIterableObject[]Object


我認為構建自己的抽象是明智的,它將以相同的方式處理集合和數組。由于沒有特定的上下文,我可以想出兩個子類的簡單想法,每個子類都定義了它的源代碼(集合或數組)應該如何迭代。然后,對接口進行編程將有助于平等地管理它們。


一個非常簡化的例子是:


interface Abstraction<T> {

    void iterate(Consumer<? super T> action);


    static <T> Abstraction<T> of(Collection<T> collection) {

        return new CollectionAbstraction<>(collection);

    }

    static <T> Abstraction<T> of(T[] array) {

        return new ArrayAbstraction<>(array);

    }

    static IntArrayAbstraction of(int[] array) {

        return new IntArrayAbstraction(array);

    }

}


class CollectionAbstraction<T> implements Abstraction<T> {

    Collection<T> source;


    public CollectionAbstraction(Collection<T> source) {

        this.source = source;

    }


    @Override

    public void iterate(Consumer<? super T> action) {

        source.forEach(action);

    }

}


class ArrayAbstraction<T> implements Abstraction<T> {

    T[] source;


    public ArrayAbstraction(T[] source) {

        this.source = source;

    }


    @Override

    public void iterate(Consumer<? super T> action) {

        for (T t : source) {

            action.accept(t);

        }

    }

}


class IntArrayAbstraction implements Abstraction<Integer> {

    int[] source;


    public IntArrayAbstraction(int[] source) {

        this.source = source;

    }


    @Override

    public void iterate(Consumer<? super Integer> action) {

        for (int t : source) {

            action.accept(t);

        }

    }

}


class Test {

    public static void main(String[] args) {

        Abstraction.of(new Integer[] {1, 2, 3}).iterate(System.out::println);

        Abstraction.of(Arrays.asList(1, 2, 3)).iterate(System.out::println);

        Abstraction.of(new int[] {1, 2, 3}).iterate(System.out::println);

    }

}

我相信上面的方法非常通用。您不依賴于某個源的迭代方式,您可以有選擇地修改它們。


查看完整回答
反對 回復 2022-09-28
?
慕碼人8056858

TA貢獻1803條經驗 獲得超6個贊

其他答案都在努力回答原始標題問題:

數組和集合是否有通用接口或超類?

但你真正的問題是在身體里:

是否有其他可能性可以像上面這樣在一個循環中處理兩者?

答案是:不,沒有辦法編寫一個循環訪問集合和數組的 for 循環。

你可以跳過一堆箍,把數組變成列表,但你幾乎肯定會得到一個比你只寫兩個(或更多)循環更大的混亂。打電話會告訴你你有什么,但如果沒有某種演員,你仍然無法使用它。 不適用于基元數組。getClass().isArray()Arrays.asList()


查看完整回答
反對 回復 2022-09-28
?
湖上湖

TA貢獻2003條經驗 獲得超2個贊

根據您要執行的操作,您可能需要實現兩種類似的方法:


public <T> void iterateOver(List<T> list) {

    // do whatever you want to do with your list

}


public <T> void iterateOver(T[] array) {

    this.iterateOver(Arrays.asList(array));

}

或者甚至可能有一個接口:


interface ExtendedIterableConsumer<T> {


    public void iterateOver(List<T> list);


    public default void iterateOver(T[] array) {

        this.iterateOver(Arrays.asList(array));


}

我不確定這是否對你有幫助,因為你似乎已經在某個變量中擁有了有問題的對象。但是,如果你能把這個問題提高一個層次,它可能會很有用。


查看完整回答
反對 回復 2022-09-28
?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

您可以使用來自isArray()Class


if (foo != null && (foo.getClass().isArray() || foo instanceof Collection<?>)){


}

編輯:


在迭代此對象方面,沒有簡單的解決方案。但是,您可以嘗試如下操作:foo


private void iterate(@NotNull Object foo) {

    if (foo instanceof Collection<?>) {

        for (Object o : ((Collection<?>) foo)) {

            chandleYourObject(o);

        }

    }


    if (foo.getClass().isArray()) {

        if (foo.getClass().isPrimitive()) {

            checkPrimitiveTypes(foo);

        }

        if (foo instanceof Object[]) {

            for (Object o : (Object[]) foo) {

                chandleYourObject(o);

            }

        }

    }

}


private void checkPrimitiveTypes(Object foo) {

    if (foo instanceof int[]) {

        for (int i : (int[]) foo) {


        }

    }

    //And the rest of primitive types

}


private void chandleYourObject(Object o ){

    //What you want to do with your object

}


查看完整回答
反對 回復 2022-09-28
?
慕絲7291255

TA貢獻1859條經驗 獲得超6個贊

數組是對象:

https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html

抽象集合還擴展了對象:

https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html

所以,是的,有一個普通的超類,但不幸的是,這并不能真正幫助你。

我建議你最好的選擇是使用:

List<> someList = Arrays.asList(sourceArray)

這會將您的數組轉換為實現 Iterable 的集合。您當然需要提前確定初始對象是數組還是集合,并且只有在數組時才調用上述內容,以下是一些執行此操作的選項:

boolean isArray = myArray.getClass().isArray();
boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());


查看完整回答
反對 回復 2022-09-28
  • 5 回答
  • 0 關注
  • 118 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號