반복자 패턴을 사용하여 객체를 문자열로 변환
JSOM, XML, Java Bean 및 기타 객체를 조작할 때 먼저 방문자 패턴을 생각할 수 있습니다. 그러나 방문자 패턴을 사용하면 호출 코드에서 콜백을 제어하기가 어렵습니다. 예를 들어 모든 콜백 하위 분기 및 리프 노드에서 분기를 조건부로 건너뛸 수 없습니다. 이 문제를 해결하려면 반복자 패턴을 사용하여 전체 개체를 탐색하고 개발자가 쉽게 읽고 디버그할 수 있는 문자열을 생성할 수 있습니다. 이 반복자는 매우 다재다능하며 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()는 출력을 위해 부서, 배열 및 부울 값의 형식을 지정합니다. .
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, 컬렉션, 배열 및 맵을 반복해야 합니다. 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()); } } }
전체 객체를 순회하여 키-값 쌍 컬렉션을 생성합니다. toString() 대신 getValueAsString() 메서드를 사용하여 출력 형식을 지정합니다. 기본 유형, 래핑된 유형, 문자열, 날짜 및 열거형에는 원래 toString() 구현을 사용하십시오. 다른 유형의 경우 클래스 이름과 해시 값이 출력됩니다.
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 객체 반복자의 구체적인 구현
반복자 패턴을 구현하는 첫 번째 단계는 일반 반복자 인터페이스인 IObjectIterator를 만드는 것입니다. 이 인터페이스는 탐색된 객체가 Java Bean, 배열 또는 맵인지 여부에 관계없이 사용할 수 있습니다.
public interface IObjectIterator { boolean next(); String getName(); Object getValue(); }
이 인터페이스를 사용하면 현재 속성의 이름과 값을 단일 순서로 얻을 수 있습니다.
IObjectIterator를 구현하는 클래스는 특정 유형의 개체를 처리하는 데 사용됩니다. 대부분의 클래스는 getName()을 호출하여 이름 접두사를 반환합니다. ArrayIterator는 요소의 인덱스를 사용합니다: 반환 이름 + "[" + nextIndex + "]";.
Property Iterator
PropertyIterator는 아마도 가장 중요한 반복 클래스일 것입니다. 이는 Java Bean 내부 검사를 사용하여 객체 속성을 읽고 이를 일련의 키-값 쌍으로 변환합니다.
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); } } }
Array Iterator
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个字符。
总结
本文介绍了如何使用迭代器模式遍历包含各种复杂属性的对象。关键是将每种类型的迭代委派给各自的类实现。可以在你自己的软件中使用这两个工具。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

Java 프로그래밍에서 Iterator 및 Iterable 인터페이스는 컬렉션의 요소를 처리하는 데 중요한 도구입니다. Iterator 인터페이스는 컬렉션 요소에 대한 반복적인 액세스를 위한 메서드를 제공하는 반면, Iterable 인터페이스는 컬렉션의 요소가 Iterator를 통해 액세스될 수 있도록 컬렉션의 반복성을 정의합니다. 둘 사이의 긴밀한 협력은 컬렉션 요소를 탐색하는 일반적인 방법을 제공합니다. Iterator 인터페이스 Iterator 인터페이스는 다음 메소드를 정의합니다. booleanhasNext(): 컬렉션에 아직 요소가 있는지 확인합니다. Enext(): 컬렉션의 다음 요소를 반환합니다. voidremove(): 현재 요소를 제거합니다. 반복 가능

Iterator 인터페이스 Iterator 인터페이스는 컬렉션을 순회하는 데 사용되는 인터페이스입니다. hasNext(), next() 및 Remove()를 포함한 여러 메소드를 제공합니다. hasNext() 메서드는 컬렉션에 다음 요소가 있는지 여부를 나타내는 부울 값을 반환합니다. next() 메서드는 컬렉션의 다음 요소를 반환하고 컬렉션에서 제거합니다. Remove() 메서드는 컬렉션에서 현재 요소를 제거합니다. 다음 코드 예제에서는 Iterator 인터페이스를 사용하여 컬렉션을 반복하는 방법을 보여줍니다. Listnames=Arrays.asList("John","Mary","Bob");Iterator

개념적 차이점: Iterator: Iterator는 컬렉션에서 값을 얻는 반복자를 나타내는 인터페이스입니다. MoveNext(), Current() 및 Reset()과 같은 메서드를 제공하여 컬렉션의 요소를 순회하고 현재 요소에 대해 작업을 수행할 수 있습니다. Iterable: Iterable은 반복 가능한 객체를 나타내는 인터페이스이기도 합니다. 컬렉션의 요소 탐색을 용이하게 하기 위해 Iterator 객체를 반환하는 Iterator() 메서드를 제공합니다. 사용법: Iterator: Iterator를 사용하려면 먼저 Iterator 객체를 얻은 후 MoveNext() 메서드를 호출하여 다음 객체로 이동해야 합니다.

Java에서 컬렉션은 이러한 요소를 저장, 검색 및 작동하기 위한 통합 인터페이스와 메서드를 제공하는 요소의 컬렉션입니다. Iterator 및 Iterable은 컬렉션 요소 순회를 위한 공통 메커니즘을 제공하는 두 가지 중요한 Java 인터페이스입니다. Iterator 인터페이스는 컬렉션 순회를 위한 hasNext() 및 next() 메소드를 정의합니다. hasNext() 메소드는 컬렉션에 탐색되지 않은 요소가 있는지 확인하는 데 사용되며, next() 메소드는 현재 요소를 반환하고 다음 요소로 이동하는 데 사용됩니다. Iterable 인터페이스는 컬렉션의 요소를 순회하기 위해 Iterator 객체를 반환하는 iterator() 메서드를 정의합니다.

Iterator 소개 Iterator는 컬렉션 탐색을 위한 Java의 인터페이스입니다. 컬렉션의 요소에 순차적으로 액세스할 수 있는 메서드 집합을 제공합니다. Iterator를 사용하여 List, Set, Map과 같은 컬렉션 유형을 반복할 수 있습니다. 데모 코드: Listlist=newArrayList();list.add("one");list.add("two");list.add("two");Iteratoriterator=list.iterator();while(iter

Iterator 인터페이스 Iterator 인터페이스는 컬렉션 탐색을 위한 Java 컬렉션 프레임워크의 하위 수준 인터페이스입니다. 이는 두 가지 주요 메소드를 정의합니다: hasNext(): 컬렉션에 더 많은 요소가 있는지 확인합니다. next(): 컬렉션의 다음 요소를 반환합니다. Iterator 인터페이스는 컬렉션에서 현재 요소를 제거하는 데 사용되는 Remove() 메서드와 같은 일부 선택적 메서드도 정의합니다. Iterator 인터페이스 사용하기 Iterator 인터페이스를 사용하면 다음 단계에 따라 컬렉션을 탐색할 수 있습니다. 컬렉션의 Iterator 객체를 가져옵니다. 컬렉션에 추가 요소가 있는지 확인하려면 hasNext() 메서드를 사용하세요. 요소가 더 있으면 next() 메서드를 사용하여 다음 요소를 가져옵니다.

Java 문서 해석: HashSet 클래스의 iterator() 메소드 사용법에 대한 자세한 설명이 필요합니다. Java 프로그래밍에서 HashSet은 일반적으로 사용되는 컬렉션 클래스 중 하나이며 Set 인터페이스를 상속합니다. AbstractSet 클래스. HashSet 클래스의 iterator() 메서드는 HashSet의 요소를 순회하기 위한 반복자 객체를 반환하는 데 사용됩니다. 이번 글에서는 HashSet 클래스의 iterator() 메소드 사용법을 자세히 설명하고,

Iterator(Iterator)와 Iterable 객체(Iterable)는 Java 컬렉션 프레임워크에서 매우 중요한 두 가지 인터페이스입니다. 컬렉션의 특정 구현을 알지 못해도 컬렉션의 요소를 반복할 수 있습니다. Iterator 인터페이스는 hasNext() 및 next()를 포함하여 컬렉션을 탐색하기 위한 메서드를 정의합니다. hasNext() 메서드는 컬렉션에 추가 요소가 있는지 확인하고, next() 메서드는 컬렉션의 다음 요소를 반환합니다. Iterable 인터페이스는 Iterator() 메소드인 Iterator를 생성하는 메소드를 정의합니다. 이 메서드는 컬렉션을 반복하는 데 사용할 수 있는 Iterator 개체를 반환합니다. 다음은 Itera를 사용하고 있습니다
