总目录
这是一个最简单的查找算法,就是从数组的第一个元素开始,依次遍历去查找每一个元素,如果发现元素内容符合,就返回元素所在的位置,否则就一直查找下去。
使用Java数组这个数据结构代码非常好实现,但是今天要使用Stream类来实现,就需要把数组的生成,查找的过程,以及最终返回查找到的数据在数组的位置(也就是下标)值都用Stream有关方法来实现,这就需要用到一些特殊的方式。
难点:Stream生成的流,是没有位置信息的
流可以想象成挤在一起的无序队伍,把数组元素放入到流中,然后随机挑选一个元素,按照给定的逻辑来处理这个数据(当然这是一种理想的处理方式),所以把数组元素放入到流中,就彻底失去了其在数组中天然的位置信息:下标。
为了解决这个问题,我们把数组元素放入到流中前,先把其变成一个map,让其主键值为其在数组中的下标,其value就是数组元素下标对应的值,这个思想来自于这里
难点:不用for或while循环
这是文章的重点,也是可以发挥Stream强大功能的地方
代码
// int len = 8;// 测试时可以把这个值设得小一些
int len = 1_000_000;// 这是Java对于大一些数的新型写法
// 用Stream生成一个随机数组成的流,使用limit(len)来限制其长度
int[] array = IntStream.generate(() ->
new Random().nextInt(len)).distinct().limit(len).toArray();
// 上面使用distinct来保证流中数据没有重复的
// 为了更好测试数据,可以不用这个随机数流来,写一个递增流来看数据变化,更好测试。
// int[] array = IntStream.range(0, len).toArray();// 是类似0,1,2,3,……这样的数列,不包含len
// 接下来定义保存map数据对的集合
Map<Integer, Integer> map = new HashMap<>();
// 生成map数据对到上面集合中
IntStream.range(0, array.length).boxed().forEach(i -> map.put(i, array[i]));
// 执行查找,对比,并将找到元素提取出来,关键是一行就可以完成
// filter中的len -1就是想要查找的值,为了模拟这个元素在数组最后一位,这样可以让查找从头一直运行到尾
Optional<Map.Entry<Integer, Integer>> first = map.entrySet().stream().parallel()
.filter(e -> e.getValue() == len - 1).findFirst();
// 将查找的数组下标值输出出来
System.out.println(first.get().getKey());
这个代码个人认为最好的地方在于,没有使用任何通常的循环语句。而使用parallel可以更好利用并行效力。