Java中关于迭代器的使用详解
这篇文章主要介绍了java 中迭代器的使用方法详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
java 中迭代器的使用方法详解
前言:
迭代器模式将一个集合给封装起来,主要是为用户提供了一种遍历其内部元素的方式。迭代器模式有两个优点:①提供给用户一个遍历的方式,而没有暴露其内部实现细节;②把元素之间游走的责任交给迭代器,而不是聚合对象,实现了用户与聚合对象之间的解耦。
迭代器模式主要是通过Iterator接口来管理一个聚合对象的,而用户使用的时候只需要拿到一个Iterator类型的对象即可完成对该聚合对象的遍历。这里的聚合对象一般是指ArrayList,LinkedList和底层实现为数组等拥有一组相同或相似特性的对象。通过迭代器模式对聚合对象的遍历主要是通过Iterator接口的next(),hasNext()方法进行的,这里next()方法将返回当前遍历点的元素值,而hasNext()方法则表征当前遍历点之后还有没有元素。Iterator接口中还有一个remove()方法,该方法将移除当前遍历点的元素。在一般情况下不需要使用该方法,一些特殊的情况可以调用该方法,如果当前聚合对象的遍历不支持该操作,那么可以在该方法中跑出UnSupportedOperationException。
这里我们以如下例子来对迭代器模式进行说明。现有两个餐厅的两套菜单,一套菜单是使用数组实现的,而另外一套菜单是使用ArrayList实现的。现在由于两个餐厅的合并而需要将两套菜单进行整合,由于双方的厨师都已经习惯了各自的菜单组装方式,因而都希望各自继续维护各自的菜单样式。但是,对于服务员来说,其为顾客提供菜单的时候则必须根据两套菜单进行两种不同方式的处理,这必然会增加服务员的工作难度,而且,如果后期有新的餐厅合并进来,比如其使用的菜单种类为HashMap,那么服务员将又会维护这一套菜单,这也不利于扩展。根据服务员的需求,其需要的是一个菜单列表,如果其面向的是各个不同的菜单类,那么势必会增加其工作难度,并且各个不同的菜单类中所提供的方法也不一定是服务员所需要的,因而,根据服务员的需求,这里需要制定一个菜单的规范,以实现服务员能够按照同一种方式对其进行遍历。这里就可以使用到迭代器模式,服务员只需要面向迭代器接口进行遍历,而各个厨师所拥有的菜单只需要实现该迭代器即可,其依然可以按照各自的方式维护其菜单项。这样就实现了不同的菜单与服务员的解耦。以下是使用迭代器模式解决该问题的具体代码。
菜单接口(主要包含创建迭代器的方法):
public interface Menu<T> { Iterator<T> createIterator(); }
菜单项:
public class MenuItem { private String name; private String description; private boolean vegetarian; private double price; public MenuItem(String name, String description, boolean vegetarian, double price) { this.name = name; this.description = description; this.vegetarian = vegetarian; this.price = price; } public String getName() { return name; } public String getDescription() { return description; } public boolean isVegetarian() { return vegetarian; } public double getPrice() { return price; } }
菜单类(菜单项的组装方式):
public class DinerMenu implements Menu<MenuItem> { private static final int MAX_ITEMS = 6; private int numberOfItems = 0; private MenuItem[] menuItems; public DinerMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99); addItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99); addItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29); addItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05); } public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); if (numberOfItems >= MAX_ITEMS) { System.out.println("Sorry, menu is full, Can't add item to menu"); } else { menuItems[numberOfItems] = menuItem; numberOfItems++; } } @Deprecated public MenuItem[] getMenuItems() { return menuItems; } public Iterator<MenuItem> createIterator() { return new DinerMenuIterator(menuItems); } } public class PancakeHouseMenu implements Menu<MenuItem> { private ArrayList<MenuItem> menuItems; public PancakeHouseMenu() { menuItems = new ArrayList<>(); addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99); addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99); addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49); addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.49); } public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); menuItems.add(menuItem); } @Deprecated public ArrayList<MenuItem> getMenuItems() { return menuItems; } public Iterator<MenuItem> createIterator() { return menuItems.iterator(); } }
迭代器接口:
public interface Iterator<T> { boolean hasNext(); T next(); }
迭代器类:
public class DinerMenuIterator implements Iterator<MenuItem> { private MenuItem[] items; private int position = 0; public DinerMenuIterator(MenuItem[] items) { this.items = items; } @Override public boolean hasNext() { return position < items.length && items[position] != null; } @Override public MenuItem next() { return items[position++]; } @Override public void remove() { if (position <= 0) { throw new IllegalStateException("You can't remove an item until you've done at least one next()"); } if (items[position - 1] != null) { for (int i = position - 1; i < items.length - 1; i++) { items[i] = items[i + 1]; } items[items.length - 1] = null; } } } public class PancakeHouseIterator implements Iterator<MenuItem> { private ArrayList<MenuItem> items; private int position = 0; public PancakeHouseIterator(ArrayList<MenuItem> items) { this.items = items; } @Override public boolean hasNext() { return position < items.size(); } @Override public MenuItem next() { return items.get(position++); } }
服务员类:
public class Waitress { private Menu<MenuItem> pancakeHouseMenu; private Menu<MenuItem> dinerMenu; public Waitress(Menu<MenuItem> pancakeHouseMenu, Menu<MenuItem> dinerMenu) { this.pancakeHouseMenu = pancakeHouseMenu; this.dinerMenu = dinerMenu; } public void printMenu() { Iterator<MenuItem> pancakeIterator = pancakeHouseMenu.createIterator(); Iterator<MenuItem> dinerIterator = dinerMenu.createIterator(); System.out.println("MENU\n----\nBREAKFAST"); printMenu(pancakeIterator); System.out.println("\nLUNCH"); printMenu(dinerIterator); } private void printMenu(Iterator<MenuItem> iterator) { while (iterator.hasNext()) { MenuItem menuItem = iterator.next(); System.out.print(menuItem.getName() + ", "); System.out.print(menuItem.getPrice() + " -- "); System.out.println(menuItem.getDescription()); } } }
从上面的代码可以看出,服务员并没有针对具体的菜单进行编程,而是依赖于一个创建菜单迭代器的Menu接口和一个迭代器接口Iterator来进行编程的,服务员并不需要知道所传过来的是何种组装方式的菜单,而只需要使用实现这两个接口的菜单对象进行遍历即可,这就达到了将变化的依赖于多态而实现接口,将不变的依赖于接口的目的,从而实现服务员与菜单组装方式的分离。
迭代器模式在Java类库的集合中随处可见,这里使用的Menu就相当于Java类库中的Iterable接口,其作用是创建一个迭代器对象,而Iterator接口和Java类库的Iterator接口基本一致。这里需要说明的是,实际上让一个类实现迭代器模式在为一个类增加功能的同时也增加了该类的维护负担,因为类的基本方法是高内聚的,所谓的内聚即是实现了一套相关的完整的功能,而迭代器接口实际上也是一套完整的相关的功能,因而让一个类实现迭代器模式隐含地为这个类增加了两套不那么“内聚”的两套功能,这就会导致该类在进行功能维护的时候需要兼顾双方。在Java类库中ArrayList和LinkedList中就有体现,其不仅提供了List所有的基本的remove方法,也提供了迭代器所需要实现的remove方法,为了实现两者的统一,其不得不作一些约定,比如遍历集合的时候不能调用该类基本的remove或者add等会更改该类结构的方法。
Atas ialah kandungan terperinci Java中关于迭代器的使用详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

Panduan untuk TimeStamp to Date di Java. Di sini kita juga membincangkan pengenalan dan cara menukar cap waktu kepada tarikh dalam java bersama-sama dengan contoh.

Kapsul adalah angka geometri tiga dimensi, terdiri daripada silinder dan hemisfera di kedua-dua hujungnya. Jumlah kapsul boleh dikira dengan menambahkan isipadu silinder dan jumlah hemisfera di kedua -dua hujungnya. Tutorial ini akan membincangkan cara mengira jumlah kapsul yang diberikan dalam Java menggunakan kaedah yang berbeza. Formula volum kapsul Formula untuk jumlah kapsul adalah seperti berikut: Kelantangan kapsul = isipadu isipadu silinder Dua jumlah hemisfera dalam, R: Radius hemisfera. H: Ketinggian silinder (tidak termasuk hemisfera). Contoh 1 masukkan Jejari = 5 unit Ketinggian = 10 unit Output Jilid = 1570.8 Unit padu menjelaskan Kirakan kelantangan menggunakan formula: Kelantangan = π × r2 × h (4

Java ialah bahasa pengaturcaraan popular yang boleh dipelajari oleh pembangun pemula dan berpengalaman. Tutorial ini bermula dengan konsep asas dan diteruskan melalui topik lanjutan. Selepas memasang Kit Pembangunan Java, anda boleh berlatih pengaturcaraan dengan mencipta program "Hello, World!" Selepas anda memahami kod, gunakan gesaan arahan untuk menyusun dan menjalankan program, dan "Hello, World!" Pembelajaran Java memulakan perjalanan pengaturcaraan anda, dan apabila penguasaan anda semakin mendalam, anda boleh mencipta aplikasi yang lebih kompleks.
