Maison php教程 PHP开发 使用Iterator模式将对象转成String

使用Iterator模式将对象转成String

Dec 13, 2016 pm 05:46 PM
iterator

操纵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));
    }
 
}
Copier après la connexion

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
Copier après la connexion

对象迭代器

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());
        }
    }
 
}
Copier après la connexion

通过遍历整个对象生成键值对的集合。使用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
...
Copier après la connexion

Java对象迭代器的具体实现

实现iterator模式的第一步是创建通用的迭代器接口:IObjectIterator。无论遍历的对象是Java bean、数组还是map都可以使用该接口。

public interface IObjectIterator {
    boolean next();
    String getName();
    Object getValue();
}
Copier après la connexion

使用该接口可以按照单一顺序依次获取当前属性的name和value。

实现了IObjectIterator的类用来处理某一种类型的对象。大多数类调用getName()返回名称前缀。ArrayIterator使用了元素的索引:return name + "[" + nextIndex + "]";。

1.png

属性迭代器

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);
        }
    }
 
}
Copier après la connexion

数组迭代器

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;
    }
 
}
Copier après la connexion

集合迭代器

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;
    }
 
    ...
 
}
Copier après la connexion

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);
    }
 
}
Copier après la connexion

字符串生成器的实现

已经看到如何遍历对象中的所有属性。最后的工作就是让输出更加美观,以及增加一些限制条件(比如不能创建一个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;
}
Copier après la connexion

代码第21行完成了格式化,增加了缩进和层次结构使显示更美观。

同时增加了一些限制条件:

第9行——限制字符串长度在16k内。

第13行——限制任何父节点下子节点数量小于64.

第21&25行——限制键和值长度在64个字符。

总结

本文介绍了如何使用迭代器模式遍历包含各种复杂属性的对象。关键是将每种类型的迭代委派给各自的类实现。可以在你自己的软件中使用这两个工具。


Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

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

Java Iterator vs Iterable : démystifier le monde des itérateurs et des objets itérables Java Iterator vs Iterable : démystifier le monde des itérateurs et des objets itérables Feb 19, 2024 pm 02:15 PM

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

Java Iterator vs Iterable : une étape vers l'écriture de code élégant Java Iterator vs Iterable : une étape vers l'écriture de code élégant Feb 19, 2024 pm 02:54 PM

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

Comparaison approfondie de Java Iterator et Iterable : analyse des avantages et des inconvénients Comparaison approfondie de Java Iterator et Iterable : analyse des avantages et des inconvénients Feb 19, 2024 pm 04:20 PM

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.

Java Iterator et Iterable : la clé du parcours de collection, démystifiée Java Iterator et Iterable : la clé du parcours de collection, démystifiée Feb 20, 2024 am 10:27 AM

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

Java Iterator vs Iterable : libérer la puissance des collections Java Java Iterator vs Iterable : libérer la puissance des collections Java Feb 19, 2024 pm 07:00 PM

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.

Java Iterator et Iterable : une analyse approfondie du mécanisme de traversée de la collection Java Java Iterator et Iterable : une analyse approfondie du mécanisme de traversée de la collection Java Feb 19, 2024 pm 08:36 PM

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

Java Iterator et Iterable : dans les coulisses de la traversée de collections Java Iterator et Iterable : dans les coulisses de la traversée de collections Feb 19, 2024 pm 04:15 PM

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 Interprétation de la documentation Java : Explication détaillée de l'utilisation de la méthode iterator() de la classe HashSet Nov 03, 2023 am 09:44 AM

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

See all articles