要一直走下去

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

所有逻辑的数据接口底层实现只有两种:
1、顺序读写-数组
2、随机读写-链表

遍历方法只有每个具体容器自己知道自己怎么遍历,
迭代器模式,让所有容器都有相同的遍历方法:
Collection接口有iterate()方法,返回Iterator接口对象

Interface Iterator_<T>
  Boolean hasNext();
  T next();

 

Collections接口:

package iterator;

interface Collection_<T> {
    void add(T t);
    int size();
    Iterator_<T> iterator_();
}

Iterator接口:

package iterator;

public interface Iterator_<T> {
    boolean hasNext();
    T next();
}

 

ArrayList实现:

package iterator;

import java.util.Arrays;

public class ArrayList_<T> implements Collection_<T> {
    private Object[] elements = new Object[10];  //数组初始化
    private int currentIndex = 0;   //下一个add的元素要放的index位置

    @Override
    public void add(T t) {
        if(currentIndex >= size()) {
            elements = Arrays.copyOf(elements, 2 * size());
        }
        elements[currentIndex] = t;
        currentIndex++;
    }

    @Override
    public int size() {
        return elements.length;
    }

    @Override
    public Iterator_<T> iterator_() {
        return new ArrayListItr<T>();
    }

    //ArrayList实现自己的迭代器类
    private class ArrayListItr<T> implements Iterator_<T>{
        private int index = 0;
        @Override
        public boolean hasNext() {
            return index < size();
        }

        @Override
        public T next() {
            return (T) elements[index++];
        }
    }

    /**
     * main方法中进行测试
     * @param args
     */
    public static void main(String[] args) {
        ArrayList_<String> strings = new ArrayList_<>();
        for(int i = 0;i<40;i++){
            strings.add("string"+i);
        }

        Iterator_<String> stringIterator_ = strings.iterator_();
        while (stringIterator_.hasNext()){
            System.out.println(stringIterator_.next());
        }
    }
}

 

LinkedList实现:

package iterator;

public class LinkedList_<T> implements Collection_<T> {
    private class Node<T>{
        T t;
        Node next;
    }
    private Node head;
    private Node tail;
    private int size;
    @Override
    public void add(T t) {
        Node<T> node = new Node<>();
        node.t = t;
        if(head == null){
            tail = head = node;
        }
        tail.next = node;
        tail = tail.next;
        size ++;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public Iterator_<T> iterator_() {
        return new LinkedListItr<T>();
    }

    /**
     * LinkedList_实现自己的迭代器类
     * @param <T>
     */
    private class LinkedListItr<T> implements Iterator_<T>{
        private Node currentNode = head;
        @Override
        public boolean hasNext() {
            return currentNode != null;
        }

        @Override
        public T next() {
            T t = (T) currentNode.t;
            currentNode = currentNode.next;
            return t;
        }
    }

    /**
     * main函数中测试
     * @param args
     */
    public static void main(String[] args) {
        LinkedList_ strings = new LinkedList_<>();
        for(int i = 0;i<40;i++){
            strings.add("string"+i);
        }

        Iterator_<String> stringIterator_ = strings.iterator_();
        while (stringIterator_.hasNext()){
            System.out.println(stringIterator_.next());
        }
    }
}

 

 

 

 

 

迭代器模式可按顺序访问集合或聚合对象中的元素,同时又无须关注集合或聚合内部的实现细节。

此模式很有用,Python语言为其提供了内置支持。实现此模式有三种方法:

一、通过序列协议实现迭代器

实现名为__getitem__()的特殊方法,此方法可接受整数做下标参数,这个下标从0开始,如果

不能继续迭代了,那么应该抛出IndexError异常。

实现__getitem__()方法后,可以像列表一样用中括号加下标的形式访问元素,例如“list[0]”

这种方式只适合所求的值与下标有映射关系的场合,如果是“斐波那契”这种迭代关系就不适用了

class AtoZ:
    def __getitem__(self, index):
        if 0 <= index < 26:
            return chr(index + ord('A'))
        raise IndexError()


# 每个字母都是根据下标直接计算
for letter in AtoZ():
    print(letter, end="")

'''
ABCDEFGHIJKLMNOPQRSTUVWXYZ
'''

 

二、通过双参数iter()函数实现迭代器

 还有个实现迭代器的办法是使用内置的iter()函数,但要传入两个参数,而不是像平常那样只传一个。

采用这种形式的时候,第一个参数必须是callable的(函数、绑定方法或其他callable对象),

第二个参数必须是个“标记值” ,没有"标记值"填None,Python才知道我们调用的是双参数iter()函数。

使用此方法制作的迭代器每次迭代都会调用callable对象(调用时不传参数),

只有当callable抛出StopIteration异常或返回标记值的时候,才停止迭代

class Presidents:
    __names = ('George Washington[乔治·华盛顿]', 'John Adams[约翰·亚当斯]',
               'Thomas Jefferson[托马斯·杰斐逊]', 'James Madison[詹姆斯·麦迪逊]',
               'James Monroe[詹姆斯·门罗]', 'John Quincy Adams[约翰·昆西·亚当斯]',
               'Andrew Jackson[安德鲁·杰克逊]', 'Martin van Buren[马丁·范布伦]',
               'William Henry Harrison[威廉·亨利·哈里森]', 'John Tyler[约翰·泰勒]',
               'James Knox Polk[詹姆斯·诺克斯·波尔克]', 'Zachary Taylor[扎卡里·泰勒]',
               'Millard Fillmore[米勒德·菲尔莫尔]', 'Franklin Pierce[福兰克林·皮尔斯]',
               'James Buchanan[詹姆斯·布坎南]', 'Abraham Lincoln[亚伯拉罕·林肯]',
               'Andrew Johnson[安德鲁·约翰逊]', 'Ulysses Grant[尤里西斯·格兰特]',
               'Rutherford B. Hayes[拉瑟福德·伯查德·海斯]', 'James A. Garfield[詹姆斯·加菲尔德]',
               'Chester A Arthur[切斯特·艾伦·阿瑟]', 'Stephen Grover Cleveland[格罗佛·克利夫兰]',
               'Benjamin Harrison[本杰明·哈里森]', 'Stephen Grover Cleveland[格罗佛·克利夫兰]',
               'William McKinley[威廉·麦金利]', 'Theodore Roosevelt[西奥多·罗斯福]',
               'William Howard Taft[威廉·霍华德·塔夫脱]', 'Thomas Woodrow Wilson[托马斯·伍德罗·威尔逊]',
               'Warren Gamaliel Harding[沃伦·甘梅利尔·哈定]', 'John Calvin Coolidge[小约翰·卡尔文·柯立芝]',
               'Herbert Clark Hoover[赫伯特·克拉克·胡佛]', 'Franklin Delano Roosevelt[富兰克林·德拉诺·罗斯福]',
               'Harry S. Truman[哈里·S·杜鲁门]', 'Dwight David Eisenhower[德怀特·戴维·艾森豪威尔]',
               'John Fitzgerald Kennedy[约翰·费茨杰拉德·肯尼迪]', 'Lyndon Baines Johnson[林登·贝恩斯·约翰逊]',
               'Richard Milhous Nixon[理查德·米尔豪斯·尼克松]', 'Gerald Rudolph Ford    [杰拉尔德·鲁道夫·福特]',
               'James Earl Carter[吉米·卡特]', 'Ronald Wilson Reagan[罗纳德·威尔逊·里根]',
               'George Herbert Walker Bush[乔治·赫伯特·沃克·布什]', 'Bill Clinton[比尔·克林顿]',
               'George Walker Bush[乔治·沃克·布什]', 'Barack Hussein Obama[贝拉克·奥巴马]',
               'Donald John Trump[唐纳德·特朗普]',)

    def __init__(self, first=None):
        self.index = (-1 if first is None else
                      Presidents.__names.index(first) - 1)

    def __call__(self):
        self.index += 1
        if self.index < len(Presidents.__names):
            return Presidents.__names[self.index]
        raise StopIteration()


def main():
    for president in iter(Presidents("Ronald Wilson Reagan[罗纳德·威尔逊·里根]"), None):
        print(president, end="  *  ")
    print()
    for president in iter(Presidents("Ronald Wilson Reagan[罗纳德·威尔逊·里根]"),
                          "Barack Hussein Obama[贝拉克·奥巴马]"):
        print(president, end="  *  ")


if __name__ == '__main__':
    main()

'''
Ronald Wilson Reagan[罗纳德·威尔逊·里根]  *  George Herbert Walker Bush[乔治·赫伯特·沃克·布什]  *  Bill Clinton[比尔·克林顿]  *  George Walker Bush[乔治·沃克·布什]  *  Barack Hussein Obama[贝拉克·奥巴马]  *  Donald John Trump[唐纳德·特朗普]  *  
Ronald Wilson Reagan[罗纳德·威尔逊·里根]  *  George Herbert Walker Bush[乔治·赫伯特·沃克·布什]  *  Bill Clinton[比尔·克林顿]  *  George Walker Bush[乔治·沃克·布什]  *  
'''

 

三、通过迭代器协议实现迭代器

该协议要求类必须有名为__iter__()的特殊方法,而且该方法要返回迭代器对象。

迭代器对象的__iter__()方法必须返回迭代器自身,而__next__()方法则返回下一个元素,

如果没有元素可供迭代,则抛出StopIteration异常。

而要实现__iter__()方法,最容易地方式则是令其成为生成器,或令其返回生成器,因为生成器本身就符合迭代器协议。

创建一个“包(bag)”类,它与set类似,但其中可容纳重复的元素。为这个包增加迭代功能,现在我们用第三种方式来实现。

 

---包(bag)类:

class Bag:
    '''
    Bag:与集合类似,只是元素允许重复
    '''
    def __init__(self, items=None):
        self.__bag = {}
        if items is not None:
            for item in items:
                self.add(item)

    def add(self, item):
        self.__bag[item] = self.__bag.get(item, 0) + 1

    def __delitem__(self, item):
        # del bag['xx']
        if self.__bag.get(item) is not None:
            self.__bag[item] -= 1
            if self.__bag[item] <= 0:
                del self.__bag[item]
        else:
            raise KeyError(str(item))

    def count(self, item):
        return self.__bag[item]

    def __len__(self):
        # len(bag)
        return sum(count for count in self.__bag.values())

    def __contains__(self, item):
        # 'xx' in bag
        return item in self.__bag

    def __str__(self):
        return self.__bag.__str__()

 

--实现__iter__()方法,令其成为生成器:

class Bag:
    '''
    Bag:与集合类似,只是元素允许重复
    '''# 实现__iter__()方法,令其成为生成器
    def __iter__(self):
        for item, count in self.__bag.items():
            for _ in range(count):
                yield item
    
if __name__ == '__main__':
    print({'a': 1, 'b': 1}.items())
    # dict_items([('a', 1), ('b', 1)])

 

--实现__iter__()方法,令其返回生成器:

class Bag:
    '''
    Bag:与集合类似,只是元素允许重复
    '''

    # 实现__iter__()方法,令其返回生成器
    def __iter__(self):
        return (item for item, count in self.__bag.items() 
                for _ in range(count))

if __name__ == '__main__':
    print({'a': 1, 'b': 1}.items())
    # dict_items([('a', 1), ('b', 1)])

 

尽管这个Bag写的很好,但大家别忘了,标准库里还有个类已经实现了此功能,那就是collections.Counter

posted on 2019-10-11 13:07  要一直走下去  阅读(164)  评论(0编辑  收藏  举报