简道云

Java 集合算法

我要纠错

Java集合教程 - Java集合算法

列表排序

Collection类中的两个静态方法会对List进行排序。

  • sort(List list)按照由元素实现的Comparable接口定义的顺序对List中的元素进行排序。
  • sort(List list,Comparator c)使用传入的Comparator对象对元素进行排序。

我们还可以使用List接口中的sort(Comparator c)对List进行排序,而不使用Collections类。

以下代码演示了如何对 List 进行排序:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("J");
    list.add("R");
    list.add("C");
    list.add("X");

    System.out.println("List: " + list);

    // Uses Comparable implementation in String class
    // to sort the list in natural order
    Collections.sort(list);
    System.out.println("Sorted List:  " + list);

  }
}

上面的代码生成以下结果。


例子

以下代码使用List接口中的sort()方法按其元素长度的升序对列表进行排序:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    System.out.println("List: " + list);

    // Uses List.sort() method with a Comparator
    list.sort(Comparator.comparing(String::length));

    System.out.println("Sorted List:  " + list);

  }
}

上面的代码生成以下结果。

sort()方法使用修改的mergeesort算法,这是一个稳定的排序。

在稳定的排序中,相等的元素将在排序操作之后保持在它们当前的位置。

排序提供了 n*log(n)性能,其中 n 是列表中元素的数量。


搜索列表

Collections类中的两个静态binarySearch()方法在List中搜索键。

该方法使用二分搜索算法执行搜索。

int  binarySearch(List list,  T  key)
int  binarySearch(List list, T  key, Comparator c)

List 必须按升序排序,然后才能使用 binarySearch()方法。

如果在列表中找到该键,则该方法将在列表中返回其索引。

如果在列表中没有找到键,它返回( - (insertion_index)-1),其中 Math.abs(( - (insertion_index)-1))是我们可以插入这个键的索引仍然保持列表订购。

在列表中找不到键时,返回值为负值。

以下代码段显示了如何使用此方法:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    int index = Collections.binarySearch(list, "CSS");
    System.out.println("CSS in List  is at " + index);

    index = Collections.binarySearch(list, "Javascript");
    System.out.println("Javascript in List is  at " + index);

  }
}

上面的代码生成以下结果。

由于“Javascript”不在列表中,二进制搜索返回-3。这意味着如果在列表中插入“Javascript”,它将被插入索引2,使用表达式( - ( - 2 + 1))计算。

随机播放列表

Shuffle给我们一个列表中的元素的随机排列。

来自Collections类的shuffle()方法的两个版本如下:

void  shuffle(List list)
void  shuffle(List list, Random  rnd)

以下代码显示如何使用shuffle方法。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    Collections.shuffle(list);
    System.out.println("List: " + list);

    Collections.shuffle(list);
    System.out.println("List: " + list);
  }
}

上面的代码生成以下结果。

反向列表

我们可以使用 Collections 类的 reverse()的静态方法来反转列表中的元素。

void  reverse(List list)

以下代码显示如何使用 reverse()方法。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    Collections.reverse(list);
    System.out.println("List: " + list);

  }
}

上面的代码生成以下结果。

交换列表项

交换交换列表中的两个元素。

Collections类的 swap()静态方法执行交换。

void  swap(List list, int i, int j)

i j 是两个元素的索引,它们必须在0和size-1之间,其中size是List的大小。

以下代码显示了如何使用这些方法对List的元素重新排序。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    // Swap elements at indexes 1 and 3
    Collections.swap(list, 1, 3);
    System.out.println(list);

  }
}

上面的代码生成以下结果。

旋转列表

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    // Rotate elements by 2
    Collections.rotate(list, 2);
    System.out.println("After  Rotating by  2: " + list);

  }
}

上面的代码生成以下结果。

创建集合的不同视图

我们可以使用Collections类的asLifoQueue()静态方法创建Deque的LIFO队列视图:

<T> Queue<T> asLifoQueue(Deque<T>  deque)

要将Map的实现用作Set实现,请使用Collections类的 newSetFromMap()静态方法:

<E> Set<E> newSetFromMap(Map<E, Boolean>  map)

只读集合视图

当将集合传递到其他方法时,我们可以获取集合的只读视图,并且我们不希望被调用的方法修改集合。

Collections类提供了以下方法来获取不同类型集合的只读视图:

<T> Collection<T> unmodifiableCollection(Collection<?  extends T> c)
<T> List<T>  unmodifiableList(List<?  extends T> list)
<K,V> Map<K,V>  unmodifiableMap(Map<?  extends K,?  extends V>  m)
<K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K,? extends  V>  m)
<T> Set<T> unmodifiableSet(Set<? extends T> s)
<T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T>  s)
static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T>  s)
<K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K,? extends  V>  m)

我们传递一个特定类型的集合,并获得相同类型的只读集合。

集合的同步视图

我们可以使用Collections类的以下静态方法之一获取集合的同步视图。

<T> Collection<T> synchronizedCollection(Collection<T>  c)
<T> List<T>  synchronizedList(List<T> list)
<K,V> Map<K,V>  synchronizedMap(Map<K,V> m)
<K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m)
<T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T>  s)
<T> Set<T> synchronizedSet(Set<T> s)
<T> SortedSet<T> synchronizedSortedSet(SortedSet<T>  s)
<K,V> SortedMap<K,V> synchronizedSortedMap (SortedMap<K,V> m)

检查集合

泛型为集合提供编译时类型安全。

下面的代码有一个编译时错误,因为我们试图添加Integer类型值到一个只能有String值的Set。

Set<String> s = new HashSet<>();
s.add("Hello");
a.add(new Integer(1)); // A compile-time error

我们可以通过使用以下代码绕过编译器检查:

Set<String> s = new HashSet<  >();
s.add("Hello");

Set s2 = s;
s2.add(new Integer(123)); // No  runtime exception

我们可以通过使用检查的集合避免上述错误。Collection类的以下静态方法返回特定类型的已检查集合:

<E> Collection<E> checkedCollection(Collection<E>  c, Class<E>  type)
<E> List<E>  checkedList(List<E> list, Class<E>  type)
<K,V> Map<K,V> checkedMap(Map<K,V>   m, Class<K> keyType,  Class<V> valueType)
<K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K,V>  m, Class<K> keyType,  Class<V> valueType)
<E> NavigableSet<E> checkedNavigableSet(NavigableSet<E>  s, Class<E>  type)
<E> Queue<E> checkedQueue(Queue<E> queue, Class<E>  type)
<E> Set<E> checkedSet(Set<E> s, Class<E>  type)
<K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K,V>  m, Class<K> keyType, Class<V> valueType)
<E> SortedSet<E> checkedSortedSet(SortedSet<E>  s, Class<E>  type)

下面的代码重写了上面的代码。

Set<String>  checkedSet = Collections.checkedSet(new HashSet<String>(),  String.class);
Set s2 = checkedSet;
s2.add(new Integer(1)); // Throws ClassCastException

创建空集合

Collections 类可以返回每种类型的不可变空集合对象。

它也可以返回一个空的迭代器。以下代码在Collections类中列出了这些静态方法:

<T> List<T>  emptyList()
<K,V> Map<K,V>  emptyMap()
<T> Set<T> emptySet()
<T> Iterator<T> emptyIterator()
<T> ListIterator<T> emptyListIterator()

Singleton集合

我们可以使用Collections类创建一个只有一个元素的集合。

我们必须创建这种集合对象,当一个方法接受一个集合作为其参数,我们只有一个对象传递给该方法。

这些方法如下:

<T> Set<T> singleton(T o)
<T> List<T>  singletonList(T o)
<K,V> Map<K,V>  singletonMap(K key,  V  value)

以下代码显示了如何使用Collections.singleton()方法。

Set<String> singletonSet  = Collections.singleton("Lonely");
// Throws a  runtime exception since a singleton set is immutable singletonSet.add("Hello");
二维码
建议反馈
二维码