HDFS中的Diff类——用来描述两个集合的不同

概述

Diff类,用来描述集合状态的变化,e.g.

  1. 集合中存在元素{e1, e2, e3},假设集合状态为previous
  2. 向集合中添加元素e4,此时集合中元素为{e1, e2, e3, e4},状态为current,那么可以用一个Diff对象刻画previous到current的变化,意味着已知previous,diff,可求current,反之亦然。

我们知道,对于集合操作,无非增删查改,而涉及到集合状态的变化——即集合元素的变化,有增删改三种情况,那么如何通过一个对象来描述这三种情况呢?

对于被删除的元素,单独放在一个list中;对于新添加的元素,单独放在一个list中;对于修改的元素,视为删除旧元素,增加新元素。

其中,将存放新添加元素的list称为create-list,即clist,将存放删除元素的list称为delete-list,即dlist。那么,我们可以将集合中元素的状态以一个二元组的形式表达

(0, 0)   元素既不在clist中,也不在dlist中
(c, 0)  元素在clist中,不在dlist中
(0, d)  元素不在clist中,但是在dlist中
(c, d)  元素既在clist中,也在dlist中

假设集合set1的初始状态为state1,现在创建了一个diff1对象记录集合set1的状态变化。对于任一元素element1,无论初始状态下其是否存在于set1中,它的状态都为(0, 0),即此刻它既不在diff1对象的clist中,也不在diff1对象的dlist中。元素具体的状态跃迁算法如下:

1. 当元素element1不在集合set1的初始状态state1中时:                      (0, 0)1.1 创建元素element1:将element1加入到diff1对象的clist中            (c, 0)1.1.1 创建元素element1,然后再次创建element1                  error1.1.2 创建元素element1,然后删除element1                     (0, 0)1.1.3 创建元素element1,然后修改element1                        (c', 0)1.2 删除元素elemnt1                                             error1.3 修改元素elment1                                                error2. 当元素element1在集合set1的初始状态state1中时:                     (0, 0)2.1 创建元素element1                                              (error)2.2 删除元素element1                                             (0, d)2.2.1 删除元素element1,然后创建元素element1                  (c, d)2.2.2 删除元素element1,然后删除元素element1                  error2.2.3 删除元素element1,然后修改元素element1                   error2.3 修改元素element1                                               (c, d)2.3.1 修改元素element1,然后创建元素element1                  error2.3.2 修改元素element1,然后删除元素element1                   (0, d)2.3.3 修改元素element1,然后修改元素element1                  (c', d)

相关类

1. ListType

枚举类,Diff类用来描述list类型

public enum ListType{CREATED, DELETED
}

2. Element

即元素类,Diff类将集合中的元素包装成Element对象

public interface Element<K> extends Comparable<K>{K getKey();
}

3. Processor

public class Processor<E> {void process(E element);
}

4. Contaner

只包含一个元素的类

public class Container<E> {private final E element;private Container(E element){this.element = element;}public E getElement(){return element;}
}

5. UndoInfo

类似于rollback,在每次操作的时候,记录修改的信息,若操作失败,可通过UndoInfo对象进行回滚操作

public static class UndoInfo<E> {private final int createdInsertionPoint;private final E trashed;private final Integer deletedInsertionPoint;private UndoInfo(final int createdInsertionPoint, final E trashed, final Integer deletedInsertionPoint){this.createdInsertionPoint = createdInsertionPonit;this.trashed = trashed;this.deletedInsertionPoint = deletedInsertionPoint;}public E getTrashedElement(){return trashed;}
}

Diff类

Diff可以说是HDFS快照架构中最核心的一个类,理解了Diff,剩下的东西便迎刃而解

public class Diff<K, E extends Diff.Element<K>> {private static final int DEFAULT_ARRAY_INITIAL_CAPACITY = 4;private List<E> created;private List<E> deleted;protected Diff(){//do nothing//就是告诉子类,你们自己玩,初始化的时候不用考虑我,我自己可以的}protected Diff(final List<E> created, List<E> deleted){this.created = created;this.deleted = deleted;}public List<E> getList(final ListType type){final List<E> list = type == ListType.CREATED ? created : deleted;return list == null ? Collections.<E>emptyList() : list;}public int searchIndex(final ListType type, final K name){return search(getList(type), name);}/**关于二分查找,如果存在于list中,那么返回index;否则,返回(-(insertionpoint) - 1)**/public static <K, E extends Comparable<K>> int search(final List<E> element, final K name){return elements == null ? -1 : Collections.binarySearch(elements, name);}public E search(final ListType type, final K name){final List<E> list = getList(type);final int c = search(list, name);return c < 0 ? null : list.get(c);}public boolean isEmpty(){return (created == null || created.isEmpty()) &&(deleted == null || deleted.isEmpty());}private void insert(final ListType type, final E element, fina int i){List<E> list = type == ListType.CREATED ? created : deleted;//首先方法是private,内部方法,大概率是先调用search,发现返回值<0,即不存在所求list中,再调用insert//所以index,即i值应该是小于0的if(i >= 0){throw new AssertionError("Element already exists");}if(list == null){list = new ArrayList<E>(DEFAULT_ARRAY_INITIAL_CAPACITY);if(type == ListType.CREATED){created = list;}else if(type == ListType.DELETED){deleted = list;}}//(-(insertionpoint) - 1) = i --> insertionpoint = -i - 1list.add(-i - 1, element);}/**create()操作,rollback操作不需要借助UndoInfo对象因为create()只需要将element添加到clist中,用不到dlist的Index**/public int create(final E element){final int c = search(created, element.getKey());insert(ListType.CREATED, element, c);//这里的c是(-(insertionpoint) - 1)return c;}public void undoCreate(final E element, final int insertionPoint){remove(created, insertionPoint, element);}private static <E> void remove(final List<E> elements, final int i, final E expected){final E removed = elements.remove(-i - 1);Preconditions.checkState(expected == removed);}/**delete()操作,两种情况1. 被删除的元素element在diff中的状态为(c, x)1.1 当x=0时,证明element是新创建的元素,那么直接在clist中将其剔除即可1.2 当x=d时,证明element是被修改的元素,那么保留在dlist中即可,将其在clist中剔除2. 被删除的元素element在diff中的状态为(y, d)2.1 当y=0时,证明element已经被删除过了,此时为非法操作2.2 当y=c时,为1.2**/public UndoInfo<E> delete(final E element){final int c =search(created, element.getKey());E previous = null;Integer d = null;//对应于(c, 0)或者(c, d),然后删除,只需要将element从clist中移除即可if(c >= 0){previous.created.remove(c);}else {d = search(deleted, element.getKey());insert(ListType.DELETED, element, d);}return new UndoInfo<E>(c, previous, d);}public void undoDelete(final E element, final UndoInfo<E> undoInfo){final int c = undoInfo.createdInsertionPoint;if(c >= 0){created.add(c, undoInfo.trashed);}else{remove(deleted, undoInfo.deletedInsertionPoint, element);}}public UndoInfo modify(final E oldElement, final E newElement){Preconditions.checkArgument(oldElement != newElement);Preconditions.checkArgument(oleElement.compareTo(newElement.getKey()) == 0);final int c = search(created, newElement.getKey());E previous = null;Integer d = null;//存在于clist中,(c, x) --> (c', x)if(c >= 0){previous = created.set(c, newElement);previous = oldElement;}else{ //element既不在clist中,也不再dlist中,但是结合的初始状态下,element已存在//(0, 0) --> (c, d)d = search(deleted, oldElement.getKey());if(d < 0){insert(ListType.CREATED, newElement, c);insert(ListType.DELETED, oldElement, d);}//else (0, d),再进行修改为非法操作}//走else的时候,这里放置的是null,其实这个方法和undoModify()方法还是有些问题的return new UndoInfo<E>(c, previous, d);}public void undoModify(final E oldElement, final E newElement, final UndoInfo<E> undoInfo){final int c = undoInfo.createdInsertionPoint;//(c', x) -> (c, x)if(c >= 0){created.set(c, undoInfo.trashed);}else {final int d = undoInfo.deletedInsertionPoint;if(d < 0){remove(created, c, newElement);remove(deleted, d, oldElement);}}}/**Find an element in the previous state集合为set1,diff对象用来描述集合set1从previous到current状态的跃迁,给定一个元素element1,求其在set1为previous时对应的Element对象**/public Container<E> accessPrevious(final K name){return accessPrevious(name, created, deleted);}private static <K, E extends Diff.Element<K>> Container<E> accessPrevious(final K name, final List<E> clist, final List<E> dlist){final int d = search(dlist, name);//存在于dlist中if(d >= 0){return new Container<E> dlist.get(d);}else {final int c = search(clist, name);return c < 0 ? null : new Container<E>(null);}}//如果element存在于clist中,直接返回该元素即可// 否则,如果element不存在与dlist中,说明其当前状态为null,如果存在于dlist中,说明其状态为(Container)nullpublic Conatiner<E> accessCurrent(K name){return accessPrevious(name, deleted, created);}//集合为set1,diff对象用来描述集合set1从previous到current状态的跃迁,给定previous状态下集合的元素,通过diff对象求得current状态下集合的元素public List<E> apply2Previous(final List<E> previous){return apply2Previous(previous, getList(ListType.CREATED), getList(ListType.DELETED));}private static <K, E extends Diff.Element<K>> List<E> apply2Previous(final List<E> previous, final List<E> clist, final List<E> dlist){final List<E> tmp = new ArrayList<E>(previous.size() - dlist.size());final Iterator<E> i = previous.iterator();//将previous中不在dlist中的元素添加到tmp中for(E deleted : dlist){E e = i.next();int cmp = 0;for(; (cmp = e.compareTo(deleted.getKey())) < 0; e = i.next()){tmp.add(e);}}for(; i.hasNext()){tmp.add(i.next());}//综上,已经将previous中不在dlist中的元素添加到tmp中,但是分析一下,元素elemnt1有如下几种情况会放入dlist中//1. (0, d),就是单纯的被删除了//2. (c, d), 是被修改过的元素,那么这个元素还要在clist中找到新的状态//对于(c, 0)的元素,只需要单纯的添加一下就可以了final List<E> current = new ArrayList<E>(tmp.size() + clist.size());final Iterator<E> tmpIterator = tmp.iterator();final Iterator<E> cIterator = clist.iterator();E t = tmpIterator.hasNext() ? tmpIterator.next() : null;E c = cIterator.hasNext() ? cIterator.next() : null;for(; t != null || c != null){//未完待续}}public List<E> apply2Current(final List<E> current){return apply2Previous(current, getList(ListType.DELETED), getList(ListType.CREATED));}//合并两个diffpublic void combinePosterior(final Diff<K, E> posterior,final Processor<E> deletedProcesser) {//未完待续}
}

针对合并两个diff对象说明如下:

集合set1状态跃迁 previous–> current–> poster

diffPreToCur用来描述previous到current的状态跃迁

diffCurToPoster用来描述current到poster的状态跃迁

1. 在diffCurToPoster对象中,元素element的状态为(0, 0):什么都不用做
2. 在diffCurToPoster对象中,元素element的状态为(c, 0)2.1 在diffPreToCur对象中:(c', 0)           error2.2 在diffPreToCur对象中:(0, d')           (c, d')2.3 在diffPreToCur对象中:(c', d')      error2.4 在diffPreToCur对象中:(0, 0)         (c, 0)3. 在diffCurToPoster对象中,元素element的状态为(0, d)3.1 在diffPreToCur对象中:(c', 0)         (0, 0)3.2 在diffPreToCur对象中:(0, d')          error3.3 在diffPreToCur对象中:(c', d')     (0, d')3.4 在diffPreToCur对象中:(0, 0)          (0, d)4. 在diffCurToPoster对象中,元素element的状态为(c, d)4.1 在diffPreToCur对象中:(c', 0)         (c, 0)4.2 在diffPreToCur对象中:(0, d')          error4.3 在diffPreToCur对象中:(c', d')     (c, d')4.4 在diffPreToCur对象中:(0, 0)          (c, d)

HDFS中的Diff类——用来描述两个集合的不同相关推荐

  1. QT之在QML中使用C++类和对象的两种方式

    一 类的方式实现在QML中使用C++对象 二 对象的方式实现在QML中使用C++对象 QML其实是对ECMAScript的扩展,融合了Qt object系统,它是一种新的解释性语言,QML引擎虽然由Q ...

  2. ruby 集合 分组_在Ruby中找到两个集合之间的区别

    ruby 集合 分组 Finding differences simply means that finding elements that are uncommon between two sets ...

  3. ruby 集合 分组_将Ruby中两个集合的所有元素结合在一起

    ruby 集合 分组 In this program, we will see how we can combine the two sets? This is not a very difficul ...

  4. 在Java中,以下有关类的关联关系描述错误的是()

    1.在Java中,以下有关类的关联关系描述错误的是(A).  A.在Java中,通过对象也可以进行关系描述,他们分别为一对一.-对多.多对一和多对多. B.一对一的关系就是在本类中定义对方类型的对象 ...

  5. python中的新式类与旧式类的一些基于descriptor的概念(下)

    3. Descriptor介绍 3.1 Descriptor代码示例 3.2 定义 3.3 Descriptor Protocol(协议) 3.4 Descriptor调用方法 4. 基于Descri ...

  6. 标准C++中的string类的用法总结

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...

  7. 理解Lucene索引与搜索过程中的核心类

    理解索引过程中的核心类 执行简单索引的时候需要用的类有: IndexWriter.Directory.Analyzer.Document.Field 1.IndexWriter IndexWriter ...

  8. [转]深刻理解Python中的元类(metaclass)

    类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Pytho ...

  9. python中如何创建类的对象_python面向对象中如何建立具体的对象?

    我们现在眼前所能看到的事物,都是具体的对象.很多小伙伴在面向对象中创建对象,其实都停留在对象名称的建立,计算机中并没有具体对象的描述属性.我们想要使用python中的类,建立的对象就需要是具体的.下面 ...

最新文章

  1. iCup,USB加热饮品方案
  2. SAP MM PO Item Category 内部code的用处?
  3. iOS之深入解析App启动dyld加载流程的底层原理
  4. 内存的静态分配和动态分配的区别【转】
  5. KDE Akademy 2008 会议
  6. 王道操作系统考研笔记——2.3.2 进程互斥的软件实现方法
  7. iPhone企业应用实例分析之一:系统介绍和需求及主要用例
  8. 数据结构 树的遍历(递归遍历练习)
  9. Atitit 高等教育 中产教育 普通教育的异同 目录 1. 顶层精英教育 1 1.1. 领导力 影响力 1 1.2. 国王规范 1 1.3. 宗教领袖 1 1.4. 决策能力 1 1.5. 国际视
  10. SQL数据库置疑修复
  11. CCA分析图如何解读_微生物群落与环境因子关联:全自动的CCA/RDA分析流程!!...
  12. git lfs linux,GIT LFS 使用笔记
  13. 伺服驱动器PID调节
  14. 布尔运算(Boolean Operators)
  15. 南华大学计算机全国排名多少位,华南理工大学全国排名第几位
  16. python中的sin函数_Python sin() 函数
  17. 千锋php 靠谱吗,千锋PHP学员心得 长久的坚持不懈才能接近成功
  18. 重阳节,让我们祝天下的老年人生活幸福快乐。
  19. js实现开平方 Math.sqrt
  20. android使用google gcm接收push消息需要注意的地方

热门文章

  1. memmem()和strstr()函数
  2. xe-ajax 异步请求库
  3. BugFree邮件设置
  4. revit【土建模块】墙齐梁板,楼层间非常实用。
  5. 渡一教育公开课web前端开发JavaScript精英课学习笔记(三十)jQuery实现Tab垂直滑动
  6. python杭州培训达内
  7. Essential Grammar in Use(Third Edition)--Present perfect Unit17
  8. input的type属性和textarea标签
  9. 深入理解JDK动态代理原理,使用javassist动手写一个动态代理框架
  10. 黄聪:Python+NLTK自然语言处理学习(二):常用方法(similar、common_contexts、generate)...