使用Iterator模式将对象转成String
操纵JSOM、XML、Java bean等对象时你可能最先想到访问者模式。但是使用访问者模式很难从调用代码控制回调。比如,不能有条件的从所有回调的子分支和叶子节点跳过某个分支。解决这个问题就可以使用Iterator模式遍历整个对象,生成易于开发者阅读和调试的字符串。该迭代器具备一定的通用性,我在使用XPath查找Java对象和在StackHunter中记录异常的工具中都用到了它。
API
本文主要介绍的两个类:StringGenerator和ObjectIterator。
字符串生成器
StringGenerator工具类将对象转化为字符串,使对象可读性更好。可以用它来实现类的toString方法或者把对象的字符串表达作为日志调试代码:
package com.stackhunter.util.tostring.example; import com.stackhunter.example.employee.Department; import com.stackhunter.example.employee.Employee; import com.stackhunter.example.employee.Manager; import com.stackhunter.example.people.Person; import com.stackhunter.util.tostring.StringGenerator; public class StringGeneratorExample { public static void main(String[] args) { Department department = new Department(5775, "Sales") .setEmployees( new Employee(111, "Bill", "Gates"), new Employee(222, "Howard", "Schultz"), new Manager(333, "Jeff", "Bezos", 75000)); System.out.println(StringGenerator.generate(department)); System.out.println(StringGenerator.generate(new int[] { 111, 222, 333 })); System.out.println(StringGenerator.generate(true)); } }
StringGenerator.generate()将department,数组和boolean值进行格式化输出。
com.stackhunter.example.employee.Department@129719f4 deptId = 5775 employeeList = java.util.ArrayList@7037717a employeeList[0] = com.stackhunter.example.employee.Employee@17a323c0 firstName = Bill id = 111 lastName = Gates employeeList[1] = com.stackhunter.example.employee.Employee@57801e5f firstName = Howard id = 222 lastName = Schultz employeeList[2] = com.stackhunter.example.employee.Manager@1c4a1bda budget = 75000.0 firstName = Jeff id = 333 lastName = Bezos name = Sales [I@39df3255 object[0] = 111 object[1] = 222 object[2] = 333 true
对象迭代器
ObjectIterator使用迭代器模式遍历对象的属性,以键值对形式保存。对象中的Java bean、集合、数组及map都要进行迭代。ObjectIterator也会考虑到对象之间循环引用的处理。
package com.stackhunter.util.tostring.example; import com.stackhunter.example.employee.Department; import com.stackhunter.example.employee.Employee; import com.stackhunter.example.employee.Manager; import com.stackhunter.util.objectiterator.ObjectIterator; public class ObjectIteratorExample { public static void main(String[] args) { Department department = new Department(5775, "Sales") .setEmployees( new Employee(111, "Bill", "Gates"), new Employee(222, "Howard", "Schultz"), new Manager(333, "Jeff", "Bezos", 75000)); ObjectIterator iterator = new ObjectIterator("some department", department); while (iterator.next()) { System.out.println(iterator.getName() + "=" + iterator.getValueAsString()); } } }
通过遍历整个对象生成键值对的集合。使用getValueAsString()方法而不是toString()格式化输出。对于原始类型、包装类型、字符串、日期和枚举使用原始的toString()实现。对于其他类型输出类名和hash值。
ObjectIterator.getDepth()会增加缩进,输出更易读。调用next()之前使用nextParent()缩短当前分支跳跃到下一属性。
some department=com.stackhunter.example.employee.Department@780324ff deptId=5775 employeeList=java.util.ArrayList@6bd15108 employeeList[0]=com.stackhunter.example.employee.Employee@22a79c31 firstName=Bill ...
Java对象迭代器的具体实现
实现iterator模式的第一步是创建通用的迭代器接口:IObjectIterator。无论遍历的对象是Java bean、数组还是map都可以使用该接口。
public interface IObjectIterator { boolean next(); String getName(); Object getValue(); }
使用该接口可以按照单一顺序依次获取当前属性的name和value。
实现了IObjectIterator的类用来处理某一种类型的对象。大多数类调用getName()返回名称前缀。ArrayIterator使用了元素的索引:return name + "[" + nextIndex + "]";。
属性迭代器
PropertyIterator可能是最重要的迭代类。它使用Java bean introspection读取对象属性,将它们转化为键值对序列。
public class PropertyIterator implements IObjectIterator { private final Object object; private final PropertyDescriptor[] properties; private int nextIndex = -1; private PropertyDescriptor currentProperty; public PropertyIterator(Object object) { this.object = object; try { BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass()); properties = beanInfo.getPropertyDescriptors(); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public boolean next() { if (nextIndex + 1 >= properties.length) { return false; } nextIndex++; currentProperty = properties[nextIndex]; if (currentProperty.getReadMethod() == null || "class".equals(currentProperty.getName())) { return next(); } return true; } @Override public String getName() { if (currentProperty == null) { return null; } return currentProperty.getName(); } @Override public Object getValue() { try { if (currentProperty == null) { return null; } return currentProperty.getReadMethod().invoke(object); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } }
数组迭代器
ArrayIterator通过反射得到数组的长度,进而检索每个数据元素。ArrayIterator不关心从getValue()方法返回值的具体细节。它们一般情况下被传递给PropertyIterator。
public class ArrayIterator implements IObjectIterator { private final String name; private final Object array; private final int length; private int nextIndex = -1; private Object currentElement; public ArrayIterator(String name, Object array) { this.name = name; this.array = array; this.length = Array.getLength(array); } @Override public boolean next() { if (nextIndex + 1 >= length) { return false; } nextIndex++; currentElement = Array.get(array, nextIndex); return true; } @Override public String getName() { return name + "[" + nextIndex + "]"; } @Override public Object getValue() { return currentElement; } }
集合迭代器
CollectionIterator与ArrayIterator非常相似。使用java.lang.Iterable调用它的Iterable.iterator()方法初始化内部迭代器。
Map迭代器
MapIterator遍历java.util.Map的entry。它并不深入到每个entry的键值对,这个工作由MapEntryIterator类完成。
public class MapIterator implements IObjectIterator { private final String name; private Iterator<?> entryIterator; private Map.Entry<?, ?> currentEntry; private int nextIndex = -1; public MapIterator(String name, Map<?, ?> map) { this.name = name; this.entryIterator = map.entrySet().iterator(); } @Override public boolean next() { if (entryIterator.hasNext()) { nextIndex++; currentEntry = (Entry<?, ?>) entryIterator.next(); return true; } return false; } ... }
Map Entry迭代器
MapEntryIterator处理java.util.Map的单个entry。它只返回两个值:entry的键和值。与ArrayIterator及其他的类似,如果是复杂类型的话,它的结果可能最终传递给PropertyIterator,作为Java bean处理。
根迭代器
RootIterator返回单个元素——初始节点。可以把它想成XML文件的根节点。目的是发起整个遍历过程。
整合
ObjectIterator类作为门面角色(Facade),包装了所有的遍历逻辑。它根据最后一次getValue()的返回值类型决定哪个IObjectIterator的子类需要实例化。当子迭代器在内部创建时它在栈中保存当前迭代器的状态。它也暴露了getChild()和getDepth()方法为调用者展示当前进度。
private IObjectIterator iteratorFor(Object object) { try { if (object == null) { return null; } if (object.getClass().isArray()) { return new ArrayIterator(name, object); } if (object instanceof Iterable) { return new CollectionIterator(name, (Iterable<?>) object); } if (object instanceof Map) { return new MapIterator(name, (Map<?, ?>) object); } if (object instanceof Map.Entry) { return new MapEntryIterator(name, (Map.Entry<?, ?>) object); } if (isSingleValued(object)) { return null; } return new PropertyIterator(object); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } }
字符串生成器的实现
已经看到如何遍历对象中的所有属性。最后的工作就是让输出更加美观,以及增加一些限制条件(比如不能创建一个GB级大小的字符串)。
public static String generate(Object object) { String s = ""; ObjectIterator iterator = new ObjectIterator("object", object); ... while (iterator.next()) { if (s.length() >= MAX_STRING_LENGTH) { return s; } if (iterator.getChild() >= MAX_CHILDREN) { iterator.nextParent(); continue; } String valueAsString = iterator.getValueAsString(); s += System.lineSeparator(); s += indent(iterator.getDepth()) + truncateString(iterator.getName()); if (valueAsString == null) { s += " = null"; } else { s += " = " + truncateString(valueAsString); } } return s; }
代码第21行完成了格式化,增加了缩进和层次结构使显示更美观。
同时增加了一些限制条件:
第9行——限制字符串长度在16k内。
第13行——限制任何父节点下子节点数量小于64.
第21&25行——限制键和值长度在64个字符。
总结
本文介绍了如何使用迭代器模式遍历包含各种复杂属性的对象。关键是将每种类型的迭代委派给各自的类实现。可以在你自己的软件中使用这两个工具。

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

En programmation Java, les interfaces Iterator et Iterable sont des outils importants pour traiter les éléments des collections. L'interface Iterator fournit des méthodes d'accès itératif aux éléments de la collection, tandis que l'interface Iterable définit l'itération de la collection afin que les éléments de la collection soient accessibles via Iterator. L'étroite coopération entre les deux nous fournit une méthode générale pour parcourir les éléments de la collection. Interface Iterator L'interface Iterator définit les méthodes suivantes : booleanhasNext() : Vérifiez s'il y a encore des éléments dans la collection. Enext() : renvoie l'élément suivant de la collection. voidremove() : supprime l'élément actuel. Itérable

Interface Iterator L'interface Iterator est une interface utilisée pour parcourir les collections. Il fournit plusieurs méthodes, notamment hasNext(), next() et remove(). La méthode hasNext() renvoie une valeur booléenne indiquant s'il existe un élément suivant dans la collection. La méthode next() renvoie l'élément suivant de la collection et le supprime de la collection. La méthode Remove() supprime l'élément actuel de la collection. L'exemple de code suivant montre comment utiliser l'interface Iterator pour parcourir une collection : Listnames=Arrays.asList("John","Mary","Bob");Iterator

Différences conceptuelles : Itérateur : Iterator est une interface qui représente un itérateur qui obtient les valeurs d'une collection. Il fournit des méthodes telles que MoveNext(), Current() et Reset(), vous permettant de parcourir les éléments de la collection et d'opérer sur l'élément actuel. Iterable : Iterable est également une interface, représentant un objet itérable. Il fournit la méthode Iterator(), qui renvoie un objet Iterator pour faciliter la traversée des éléments de la collection. Utilisation : Iterator : Pour utiliser Iterator, vous devez d'abord obtenir un objet Iterator, puis appeler la méthode MoveNext() pour passer au suivant.

Introduction à IteratorIterator est une interface en Java permettant de parcourir des collections. Il fournit un ensemble de méthodes qui vous permettent d'accéder aux éléments d'une collection de manière séquentielle. Vous pouvez utiliser Iterator pour parcourir des types de collections tels que List, Set et Map. Code de démonstration : Listlist=newArrayList();list.add("one");list.add("two");list.add("trois");Iteratoriterator=list.iterator();while(iter

En Java, une collection est une collection d'éléments qui fournit une interface unifiée et des méthodes pour stocker, récupérer et exploiter ces éléments. Iterator et Iterable sont deux interfaces Java importantes qui fournissent un mécanisme commun pour parcourir les éléments de la collection. L'interface Iterator définit les méthodes hasNext() et next() pour parcourir les collections. La méthode hasNext() est utilisée pour vérifier s'il existe des éléments non traversés dans la collection, et la méthode next() est utilisée pour renvoyer l'élément actuel et le déplacer vers l'élément suivant. L'interface Iterable définit la méthode iterator(), qui renvoie un objet Iterator pour parcourir les éléments de la collection.

Interface Iterator L'interface Iterator est une interface de bas niveau dans le cadre de collection Java pour parcourir les collections. Il définit deux méthodes principales : hasNext() : vérifie s'il y a plus d'éléments dans la collection. next() : renvoie l'élément suivant de la collection. L'interface Iterator définit également certaines méthodes facultatives, telles que la méthode remove(), qui est utilisée pour supprimer l'élément actuel de la collection. Utilisation de l'interface Iterator Vous pouvez utiliser l'interface Iterator pour parcourir une collection en procédant comme suit : Obtenez l'objet Iterator de la collection. Utilisez la méthode hasNext() pour vérifier s'il y a plus d'éléments dans la collection. S'il y a plus d'éléments, utilisez la méthode next() pour obtenir l'élément suivant

Iterator (Iterator) et Iterable object (Iterable) sont deux interfaces très importantes dans le framework de collection Java. Ils vous permettent de parcourir les éléments d'une collection sans connaître l'implémentation spécifique de la collection. L'interface Iterator définit des méthodes pour parcourir les collections, notamment hasNext() et next(). La méthode hasNext() vérifie s'il y a plus d'éléments dans la collection, tandis que la méthode next() renvoie l'élément suivant dans la collection. L'interface Iterable définit une méthode pour créer un Iterator, la méthode iterator(). Cette méthode renvoie un objet Iterator qui peut être utilisé pour parcourir la collection. Ce qui suit utilise Itera

Interprétation de la documentation Java : Explication détaillée de l'utilisation de la méthode iterator() de la classe HashSet. Des exemples de code spécifiques sont nécessaires. En programmation Java, HashSet est l'une des classes de collection couramment utilisées. Elle implémente l'interface Set et hérite de la. Classe AbstractSet. La méthode iterator() de la classe HashSet est utilisée pour renvoyer un objet itérateur pour parcourir les éléments du HashSet. Cet article expliquera en détail l'utilisation de la méthode iterator() de la classe HashSet, et
