常见循环
java目前常见的循环主要有3种:
1.iterator循环
List<Integer> list = new ArrayList<Integer>();
for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
System.out.println(iterator.next());
}
2.下标循环
Integer[] list = new Integer[10];
for (int i = 0, size = list.length; i < size; i++) {
System.out.println(list[i]);
}
3.for-each循环
List<Integer> list = new ArrayList<Integer>();
for (Integer i : list) {
System.out.println(i);
}
for-each循环比较
- for-each循环优势
for-each循环不会有性能的损耗,下标循环是最快的了,for-each和它相比,性能基本差距不大,可以忽略。
for-each循环再面对多重循环时,不存在下标问题等,易于使用。例如,2重3重循环,存在很多变量。 - for-each循环使用
一般的集合、数组都可以使用for-each进行循环,同时我们也可以继承Iterable接口,实现for-each循环。只要实现了这个接口,就可以使用for-each循环了。
一下是jdk8的Iterator api:
/**
* Implementing this interface allows an object to be the target of
* the "for-each loop" statement. See
*/
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*/
Iterator<T> iterator();
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
/**
* Creates a {@link Spliterator} over the elements described by this
* {@code Iterable}.
*
* @implSpec
* The default implementation creates an
* <em><a href="Spliterator.html#binding">early-binding</a></em>
* spliterator from the iterable's {@code Iterator}. The spliterator
* inherits the <em>fail-fast</em> properties of the iterable's iterator.
*
* @implNote
* The default implementation should usually be overridden. The
* spliterator returned by the default implementation has poor splitting
* capabilities, is unsized, and does not report any spliterator
* characteristics. Implementing classes can nearly always provide a
* better implementation.
*
* @return a {@code Spliterator} over the elements described by this
* {@code Iterable}.
* @since 1.8
*/
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
注意点
以下出现的情况,不要使用for-each
- 过滤–当遍历时,需要删除元素,需要使用显示的迭代器,以便调用remove方法,推荐使用Iterator方法,安全没问题。当使用下标循环去remove集合时,容易造成下表位置移动,remove错。
- 转换
- 平行迭代
一般情况下,推荐使用for-each
快捷使用
当查找某个元素时,一般都是采用集合的contain()方法判断的,或者快捷的for循环进行判断。
一般的快速for判断
int[] list = new int[]{1, 5, 3, 7, 9, 2};
int m = 3;
boolean isContain = false;
for (int i = 0; i < list.length; i++) {
if (list[i] == m) {
isContain = true;
break;
}
}
System.out.println(isContain);
对于这种判断一般采用其他帮助类更好,如下:
System.out.println(ArrayUtils.contains(list, 3));
其中ArrayUtils的源码如下,更严谨:
public static boolean contains(int[] array, int valueToFind) {
return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
public static int indexOf(int[] array, int valueToFind) {
return indexOf(array, valueToFind, 0);
}
//int[]
public static int indexOf(int[] array, int valueToFind, int startIndex) {
if (array == null) {
return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
}
for (int i = startIndex; i < array.length; i++) {
if (valueToFind == array[i]) {
return i;
}
}
return INDEX_NOT_FOUND;
}
//Object
public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
if (array == null) {
return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
}
if (objectToFind == null) {
for (int i = startIndex; i < array.length; i++) {
if (array[i] == null) {
return i;
}
}
} else if (array.getClass().getComponentType().isInstance(objectToFind)) {
for (int i = startIndex; i < array.length; i++) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}
return INDEX_NOT_FOUND;
}