Home php教程 PHP开发 Convert object to String using Iterator pattern

Convert object to String using Iterator pattern

Dec 13, 2016 pm 05:46 PM
iterator

When manipulating JSOM, XML, Java beans and other objects, you may first think of the visitor pattern. But using the visitor pattern it is difficult to control callbacks from the calling code. For example, you cannot conditionally skip a branch from all callback sub-branches and leaf nodes. To solve this problem, you can use the Iterator pattern to traverse the entire object and generate a string that is easy for developers to read and debug. This iterator is quite versatile and I've used it in both tools for finding Java objects using XPath and logging exceptions in StackHunter.

API

This article mainly introduces two classes: StringGenerator and ObjectIterator.

String Generator

StringGenerator tool class converts objects into strings to make objects more readable. You can use it to implement the toString method of the class or use the string expression of the object as log debugging code:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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));

    }

  

}

Copy after login

StringGenerator.generate() formats department, array and boolean values ​​to output.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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

Copy after login

Object Iterator

ObjectIterator uses the iterator pattern to traverse the properties of the object and save them in the form of key-value pairs. Java beans, collections, arrays and maps in objects must be iterated. ObjectIterator also takes into account the handling of circular references between objects.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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());

        }

    }

  

}

Copy after login

Generates a collection of key-value pairs by traversing the entire object. Use the getValueAsString() method instead of toString() to format the output. Use the original toString() implementation for primitive types, wrapped types, strings, dates, and enumerations. For other types, the class name and hash value are output.

ObjectIterator.getDepth() will increase the indentation and make the output more readable. Use nextParent() before calling next() to shorten the current branch and jump to the next attribute.

1

2

3

4

5

6

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

...

Copy after login

Concrete implementation of Java object iterator

The first step to implement the iterator pattern is to create a general iterator interface: IObjectIterator. This interface can be used regardless of whether the traversed object is a Java bean, an array or a map.

1

2

3

4

5

public interface IObjectIterator {

    boolean next();

    String getName();

    Object getValue();

}

Copy after login

Use this interface to obtain the name and value of the current attribute in a single order.

Classes that implement IObjectIterator are used to process objects of a certain type. Most classes call getName() to return the name prefix. ArrayIterator uses the index of the element: return name + "[" + nextIndex + "]";.

Convert object to String using Iterator pattern

Property Iterator

PropertyIterator is probably the most important iteration class. It uses Java bean introspection to read object properties and convert them into a sequence of key-value pairs.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

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);

        }

    }

  

}

Copy after login

Array Iterator

ArrayIterator gets the length of the array through reflection, and then retrieves each data element. ArrayIterator does not care about the specific details of the value returned from the getValue() method. They are normally passed to PropertyIterator.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

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;

    }

  

}

Copy after login

集合迭代器

CollectionIterator与ArrayIterator非常相似。使用java.lang.Iterable调用它的Iterable.iterator()方法初始化内部迭代器。

Map迭代器

MapIterator遍历java.util.Map的entry。它并不深入到每个entry的键值对,这个工作由MapEntryIterator类完成。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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;

    }

  

    ...

  

}

Copy after login

Map Entry迭代器

MapEntryIterator处理java.util.Map的单个entry。它只返回两个值:entry的键和值。与ArrayIterator及其他的类似,如果是复杂类型的话,它的结果可能最终传递给PropertyIterator,作为Java bean处理。

根迭代器

RootIterator返回单个元素——初始节点。可以把它想成XML文件的根节点。目的是发起整个遍历过程。

整合

ObjectIterator类作为门面角色(Facade),包装了所有的遍历逻辑。它根据最后一次getValue()的返回值类型决定哪个IObjectIterator的子类需要实例化。当子迭代器在内部创建时它在栈中保存当前迭代器的状态。它也暴露了getChild()和getDepth()方法为调用者展示当前进度。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

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);

    }

  

}

Copy after login

字符串生成器的实现

已经看到如何遍历对象中的所有属性。最后的工作就是让输出更加美观,以及增加一些限制条件(比如不能创建一个GB级大小的字符串)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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;

}

Copy after login

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

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

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

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

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

总结

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


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Java Iterator vs. Iterable: Demystifying the World of Iterators and Iterable Objects Java Iterator vs. Iterable: Demystifying the World of Iterators and Iterable Objects Feb 19, 2024 pm 02:15 PM

In Java programming, the Iterator and Iterable interfaces are important tools for processing elements in collections. The Iterator interface provides methods for iterative access to collection elements, while the Iterable interface defines the iterability of the collection so that the elements in the collection can be accessed through Iterator. The close cooperation between the two provides us with a general method for traversing collection elements. Iterator interface The Iterator interface defines the following methods: booleanhasNext(): Check whether there are still elements in the collection. Enext(): Returns the next element in the collection. voidremove(): Remove the current element. Iterable

Java Iterator vs. Iterable: A step into writing elegant code Java Iterator vs. Iterable: A step into writing elegant code Feb 19, 2024 pm 02:54 PM

Iterator interface The Iterator interface is an interface used to traverse collections. It provides several methods, including hasNext(), next() and remove(). The hasNext() method returns a Boolean value indicating whether there is a next element in the collection. The next() method returns the next element in the collection and removes it from the collection. The remove() method removes the current element from the collection. The following code example demonstrates how to use the Iterator interface to iterate over a collection: Listnames=Arrays.asList("John","Mary","Bob");Iterator

In-depth comparison of Java Iterator and Iterable: pros and cons analysis In-depth comparison of Java Iterator and Iterable: pros and cons analysis Feb 19, 2024 pm 04:20 PM

Conceptual differences: Iterator: Iterator is an interface that represents an iterator that obtains values ​​from a collection. It provides methods such as MoveNext(), Current() and Reset(), allowing you to traverse the elements in the collection and operate on the current element. Iterable: Iterable is also an interface, representing an iterable object. It provides the Iterator() method, which returns an Iterator object to facilitate traversing the elements in the collection. Usage: Iterator: To use Iterator, you need to first obtain an Iterator object, and then call the MoveNext() method to move to the next

Java Iterator and Iterable: The key to collection traversal, demystified Java Iterator and Iterable: The key to collection traversal, demystified Feb 20, 2024 am 10:27 AM

Introduction to IteratorIterator is an interface in Java for traversing collections. It provides a set of methods that allow you to access elements in a collection in a sequential manner. You can use Iterator to iterate over collection types such as List, Set, and Map. Demo code: Listlist=newArrayList();list.add("one");list.add("two");list.add("three");Iteratoriterator=list.iterator();while(iter

Java Iterator and Iterable: Behind the Scenes of Collection Traversal Java Iterator and Iterable: Behind the Scenes of Collection Traversal Feb 19, 2024 pm 04:15 PM

Iterator (Iterator) and Iterable object (Iterable) are two very important interfaces in the Java collection framework. They enable you to iterate over the elements in a collection without knowing the specific implementation of the collection. The Iterator interface defines methods for traversing collections, including hasNext() and next(). The hasNext() method checks if there are more elements in the collection, while the next() method returns the next element in the collection. The Iterable interface defines a method for creating an Iterator, the iterator() method. This method returns an Iterator object that can be used to iterate over the collection. The following is using Itera

Java Iterator and Iterable: An in-depth analysis of Java collection traversal mechanism Java Iterator and Iterable: An in-depth analysis of Java collection traversal mechanism Feb 19, 2024 pm 08:36 PM

Iterator interface The Iterator interface is a low-level interface in the Java collection framework for traversing collections. It defines two main methods: hasNext(): checks if there are more elements in the collection. next(): Returns the next element in the collection. The Iterator interface also defines some optional methods, such as the remove() method, which is used to remove the current element from the collection. Using the Iterator interface You can use the Iterator interface to traverse a collection using the following steps: Get the Iterator object of the collection. Use the hasNext() method to check if there are more elements in the collection. If there are more elements, use the next() method to get the next element

Java Iterator vs. Iterable: Unlocking the Power of Java Collections Java Iterator vs. Iterable: Unlocking the Power of Java Collections Feb 19, 2024 pm 07:00 PM

In Java, a collection is a collection of elements that provides a unified interface and methods to store, retrieve and operate these elements. Iterator and Iterable are two important Java interfaces that provide a common mechanism for traversing collection elements. The Iterator interface defines hasNext() and next() methods for traversing collections. The hasNext() method is used to check whether there are any untraversed elements in the collection, and the next() method is used to return the current element and move it to the next element. The Iterable interface defines the iterator() method, which returns an Iterator object for traversing the elements in the collection.

Interpretation of Java documentation: Detailed explanation of the usage of iterator() method of HashSet class Interpretation of Java documentation: Detailed explanation of the usage of iterator() method of HashSet class Nov 03, 2023 am 09:44 AM

Interpretation of Java documentation: Detailed explanation of the usage of the iterator() method of the HashSet class. Specific code examples are required. In Java programming, HashSet is one of the commonly used collection classes. It implements the Set interface and inherits from the AbstractSet class. The iterator() method of the HashSet class is used to return an iterator object for traversing the elements in the HashSet. This article will explain in detail the usage of iterator() method of HashSet class, and

See all articles