Java indexOf方法作为手动搜索的捷径

chr*_*c17 2 java

我有以下Java代码,但List.indexOf()似乎做了几乎相同的事情(包括返回-1,如果没有找到.有没有办法传递indexOf()一个表达对象的想法的对象是不是0?

/**
 * Find the first non-zero element in a List of Integers
 * @param row List of Integers
 * @return -1 if all zeros in row
 * otherwise position of first non zero element
 */
public static int leading(List<Integer> row) {

 for (int i = 0; i < row.size(); i++) {
   if (row.get(i)!= 0) {
      return i;
   }
 }

 return -1;
}
Run Code Online (Sandbox Code Playgroud)

回复:ThorbjørnRavnAndersen:如果我将null传入IndexOf(),它将始终返回-1,因为我的列表总是包含整数.我想做一些像row.indexOf(Integer a where!a.equals(0))的东西.不确定是否可能

pol*_*nts 6

List.indexOf "解"

List.indexOf(Object o) 定义如下:

返回此列表中第一次出现的指定元素的索引,或者-1此列表是否包含该元素.更正式地说,返回的指数最低i,从而

(o==null ? get(i)==null : o.equals(get(i)))
Run Code Online (Sandbox Code Playgroud)

true,或者-1如果没有这样的索引.

试图给出一个"meta"元素对象是很诱人的,该元素对象并不是真正的元素,List甚至可能与它的实际元素的类型不同List,而是equals基于谓词的某个所需元素.这应该是有效的,因为它indexOf是根据给定Object oequals方法对列表中的元素进行定义(而不是相反),但是实现你想要的真正"hacky"方式.

这是一个概念证明:

// PROOF OF CONCEPT ONLY! DO NOT IMITATE!
// abusing indexOf(Object) to find index of a negative integer in List

List<Integer> nums = Arrays.asList(3,4,5,-6,7);
Object equalsNegativeInteger = new Object() {
    @Override public boolean equals(Object o) {
        return (o instanceof Integer) && ((Integer) o) < 0;
    }
};
System.out.println(nums.indexOf(equalsNegativeInteger));
// prints 3
Run Code Online (Sandbox Code Playgroud)

"meta"元素对象是equals任何否定的Integer,但是Integer永远不会有equals它.这种不对称严重违反equals合同,但它"仍然有效".


番石榴解决方案

传达意图的更好的解决方案是使用Guava的高阶函数.这是一个来自com.google.commons.collect.Iterables:

<T> int indexOf(Iterable<T> iterable, Predicate<? super T> predicate)

返回满足提供的谓词的第一个元素的iterable中的索引,或者-1如果Iterable没有这样的元素.更正式地,返回最低的索引i,使得:

 predicate.apply(Iterables.get(iterable, i))
Run Code Online (Sandbox Code Playgroud)

true,或者-1如果没有这样的索引.

片段

这里有一个片段来说明番石榴高阶函数的表达能力:

import com.google.common.collect.*;
import com.google.common.base.*;
import java.util.*;

public class IterablesPredicateExample {
    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(1,2,-3,4,-5,6,-7,-8);
        Predicate<Integer> isNegative = new Predicate<Integer>() {
            @Override public boolean apply(Integer n) {
                return n < 0;
            }
        };          
        // Get index of first negative number
        System.out.println(Iterables.indexOf(nums, isNegative));
        // 2

        // Find that number
        System.out.println(Iterables.find(nums, isNegative));
        // -3

        // Find all negative numbers
        System.out.println(Iterables.filter(nums, isNegative));
        // [-3, -5, -7, -8]

        // Are all numbers negative?
        System.out.println(Iterables.all(nums, isNegative));
        // false

        // Find all non-negative numbers
        System.out.println(Iterables.filter(nums, Predicates.not(isNegative)));
        // [1, 2, 4, 6]
    }
}
Run Code Online (Sandbox Code Playgroud)

摘要

  • List.indexOf(Object)可以滥用来查找满足给定谓词的元素,但这违反了equals合同
  • 利用番石榴的Predicate和高阶功能,如indexOf,find,filter,all,any等可以让你在一个更强大的表达方式表达这些操作

  • +1,使用谓词肯定是表达代码意图的好方法. (2认同)