`
白黑山河
  • 浏览: 46950 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
文章分类
社区版块
存档分类
最新评论

[胡扯]java和scala的链表的嵌套循环实现

阅读更多

一个很简单的问题,不过今天被问到了,一下子也说不出应该调用哪个方法,想想挺好玩:有一个linkedlist,现在要对它做遍历,对遍历到的每一个元素A,需要对从A到尾节点的所有元素再进行一次遍历,完成一个嵌套循环

 

最直接的方式就是:

 

 int index = 0;
        for (Iterator<Integer> i = list.iterator(); i.hasNext();) {
            Integer num = i.next();
            index++;

            boolean startLoopWork = false;
            int innerIndex = 0;
            for(Iterator<Integer> j = list.iterator(); i.hasNext();) {
                Integer num2 = j.next();
                innerIndex++;
                startLoopWork = startLoopWork || index == innerIndex-1;
                if (startLoopWork) {
                    // do something
                    System.out.println(num + ":" + num2);
                }
            }
        }

 

虽然直接,但是意图表达的不是很直接,那么在内层就直接对sublist进行遍历吧:

 

        int anotherIndex = 0;
        for (Iterator<Integer> i = list.iterator(); i.hasNext();anotherIndex++) {
            Integer num = i.next();

            if (anotherIndex >= list.size()) break;
            List<Integer> subList = list.subList(anotherIndex+1, list.size());
            for(Iterator<Integer> j = subList.iterator(); j.hasNext();) {
                Integer num2 = j.next();
                // do something
                System.out.println(num + ":" + num2);
            }
        }
 

 

这个实际上也就是list.listIterator(index)做的事情,恩,list已经有这样的一个接口了:

 

for (ListIterator<Integer> i = list.listIterator(); i.hasNext();) {
            Integer num = i.next();

            for (Iterator<Integer> innerIterator = list.listIterator(i.nextIndex()); innerIterator.hasNext();) {
                Integer innerNum = innerIterator.next();
                // do something
                System.out.println(num + ":" + innerNum);
            }
        }

 

这样的实现下,innerIterator是一个O(n)算法,不过由于链表中的元素是private的Entry对象,对外不可见,所以...我觉得这个限制使得扩展性不够好,不知道有什么特别考虑么?望知道的朋友告知

 

最后看一个scala的实现,scala中对链表统一抽象成head::rest:

 

@tailrec
def doubleIterate[A](list: List[A])(f: (A, Option[A]) => Unit): Unit = {
    list match {
      case (head :: Nil) => f(head, None)
      case (head :: rest) =>
        rest.foreach (each => f(head, Some(each)))
        doubleIterate(rest)(f)
    }
  }

 

借助了scala的模式匹配机制,虽然写起来一样的繁琐,但是意图表达的比较清楚

 

这个实现的问题是只能应用于链表,而无法应用到其他的可以迭代的结构,比如array,string等,不过scala中并没有提供像java这样直接的api,所以为了能对所有具有iterable特性的数据结构进行这样的操作,还是只能回到原始的做法:

 

 def doubleIterateIterable[A](iterable: Iterable[A])(f: (A, A) => Unit) = {
    var index = 0
    iterable.foreach { i =>
      index = index + 1
      iterable.iterator.drop(index).foreach(j => f(i, j))
    }
  }

这里,间接性主要来自于闭包,不过scala的iterable特性没有提供foreachWithIndex这样的方法。话说java中应该也有类似drop的接口吧。 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics