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

Java indexOf方法作为手动搜索的捷径,java,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 el

我有下面的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;
}
/**
*在整数列表中查找第一个非零元素
*@param整数行列表
*@return-1如果行中的所有零
*否则,第一个非零元素的位置
*/
公共静态整型前导(列表行){
对于(int i=0;i

Re:Thorbjørn Ravn Andersen:如果我将null传递给IndexOf(),它将始终返回-1,因为我的列表总是包含整数。我想执行类似于row.IndexOf(整数a其中!a.equals(0))的操作。不确定是否可能

我不相信标准运行时库中存在这样的方法

问题是,您是否需要这样做,以便跟踪非零值,或者您可以使用蛮力搜索。我将使用后者,并跟踪System.currentMillis()之间的差异如果它超过了您决定的限制,请记录它,这样您就不必运行探查器来定位已知的可能瓶颈

还请注意,您在示例中进行了自动装箱。这种开销可能是不必要的。

该方法将返回找到指定
对象的第一个索引

问题中给出的代码似乎有以下要求:

  • 返回列表中找不到
    0
    的第一个索引
  • 如果列表中不存在此类元素,则返回
    -1
不幸的是,无法使用
indexOf
方法表达上述内容

因此,您提供的代码似乎是可接受的需求实现。

List.indexOf
“解决方案” 定义如下:

返回此列表中指定元素第一次出现的索引,如果此列表不包含该元素,则返回
-1
。更正式地说,返回最低索引
i
,以便

(o==null ? get(i)==null : o.equals(get(i)))
,如果没有此类索引,则为
-1

试图给出一个“元”是很诱人的元素对象,该对象实际上不在
列表中,甚至可能与
列表中的实际元素类型不同,但是
等于基于谓词的某个所需元素。这应该有效,因为
indexOf
是根据给定的
对象o
equals
来定义的hod针对列表中的一个元素(而不是相反),但这是一种真正的“黑客”方式来实现您想要的

以下是概念证明:

// 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
,如果没有此类索引,则为
-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]
    }
}
import com.google.common.collect.*;
导入com.google.common.base.*;
导入java.util.*;
公共类IterablesPredicateExample{
公共静态void main(字符串[]args){
List nums=Arrays.asList(1,2,-3,4,-5,6,-7,-8);
谓词isNegative=新谓词(){
@覆盖公共布尔应用(整数n){
返回n<0;
}
};          
//获取第一个负数的索引
System.out.println(Iterables.indexOf(nums,isNegative));
// 2
//找到那个号码
System.out.println(Iterables.find(nums,isNegative));
// -3
//找到所有负数
System.out.println(Iterables.filter(nums,isNegative));
// [-3, -5, -7, -8]
//所有的数字都是负数吗?
System.out.println(Iterables.all(nums,isNegative));
//假的
//查找所有非负数
System.out.println(Iterables.filter(nums,谓词.not(isNegative));
// [1, 2, 4, 6]
}
}

总结
  • List.indexOf(Object)
    可以被滥用来查找满足给定谓词的元素,但这违反了
    等于
    契约
  • 使用番石榴和更高阶函数,如
    indexOf
    find
    filter
    all
    any
    等,可以让您以更有力的表达方式来表达这些操作

不,java不支持闭包


标准的解决方法是使用匿名内部类,但这需要足够的样板代码,以使解决方案与实现该循环一样复杂。

不是0?你的意思是
null
?+1,使用谓词肯定是表达代码意图的一个好方法。@coobird:只是不要对我的证明投反对票f-concept“hack”part=)我只是想说明,单独使用
List.indexOf(Object)
绝对不是不可能的(但你可能不想用番石榴替代品这样做)。hack(+1表示它是一种hack)可能只在列表实现调用
equalsNegativeInteger.equals(e)时才起作用
而不是
e.equals(equalsNegativeInteger)
,因为equals方法不是对称的+1不管怎样,对于谓词方法。@Willi:文档确实说“形式上”它是
o.equals(e)
,而不是相反,但我不确定这个合同遵守得有多严格。最终,如果一个
列表
实现使用
e.equals(o)
而违反了该
indexOf
契约,并且黑客攻击失败,那么您不能抱怨,因为您首先违反了
equals
契约。
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]
    }
}