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");