java集合辅助类 Collections、Arrays

 

Arrays、Collections

 

1 )数组集合之间转换

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

     a)Arrays.asList()这个方法是用传入的数组作为底层实现的,因此不能不改变大小,即“固定尺寸”

     b)注意这里返回的ArrayList 是Arrays的内部类

     c)因为不能改变大小,所以并没实现增删方法,涉及到这些操作,会抛出异常

          UnsupportedOperationException;表示不支持请求的操作

		List<String> list =Arrays.asList("数组");
		//不能这样操作
		list.add("java.lang.UnsupportedOperationException");

 

     d)因为修改没有违反“尺寸固定”,所以可以通过set(int index, E element)对List元素进行修改,当然也

          会关联的修改数组

     e)  所以在将数组转成集合时,应把ArrayList.asList()的结果作为构造器的参数传递给任何的

          Collection(或者使用addAll()方法,或Collections.addAll()静态方法),

          可以这样处理:

//方法1
List<String> list = new ArrayList<String>(Arrays.asList("数组"));
//方法2
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("数组"));
//方法3
Collections.addAll(list, "数组");

 

     f)将集合转换成数组,Set同样适用

		List<String> list = new ArrayList<String>(Arrays.asList("数组"));
		//默认返回的Object数组
		Object[] obj1 = list.toArray();
		//不能用强制类型转换,运行时报错
		//String[] str1 = (String[]) list.toArray();
		//可以传入一个空的数组,目的告诉toArray要转换的类型
		String[] str2 =  list.toArray(new String[0]);
		//直接传入一个等大小的数组进去
		String[] str3 = new String[list.size()];
		list.toArray(str3);

 

 

2 )Collections可利用现有容器生成不可修改容器      

  //传入任何Collection子类,返回一个不可修改Collection对象
  public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)
  //传入ArrayList、LinkedList ,返回不可修改的List
  public static <T> List<T> unmodifiableList(List<? extends T> list)
  //传入HashSet ,返回不可修改Set
  public static <T> Set<T> unmodifiableSet(Set<? extends T> s)
  //传入TreeSet ,返回不可修改SortedSet
  public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)
   //传入HashMap ,返回不可修改Map
  public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m)
  //传入TreeMap ,返回不可修改SortedMap
  public static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K, ? extends V> m)

     a)返回一个只读集合,这样别人只能看到,不能修改内容

     b)可通过原引用对集合进行修改

     b)上面都是Collections中方法

     c)返回的不可修改容器,通过将原容器包装(装饰者模式),将每个涉及到修改容器的方法都返回

           UnsupportedOperationException 

     d) 看一个实例代码

		List<String> list = new ArrayList<String>(Arrays.asList("数组"));
		List<String> unmodif = Collections.unmodifiableList(list);
		unmodif.add("java.lang.UnsupportedOperationException");

 

 

 3)Collections可利用现有容器生成同步容器     

  //传入任何Collection子类,返回一个同步Collection对象
  public static <T> Collection<T> SynchronizedCollection(Collection<? extends T> c)
  //传入ArrayList、LinkedList ,返回同步的List
  public static <T> List<T> SynchronizedList(List<? extends T> list)
  //传入HashSet ,返回同步Set
  public static <T> Set<T> SynchronizedSet(Set<? extends T> s)
  //传入TreeSet ,返回同步SortedSet
  public static <T> SortedSet<T> SynchronizedSortedSet(SortedSet<T> s)
   //传入HashMap ,返回同步Map
  public static <K,V> Map<K,V> SynchronizedMap(Map<? extends K, ? extends V> m)
  //传入TreeMap ,返回同步SortedMap
  public static <K,V> SortedMap<K,V> SynchronizedSortedMap(SortedMap<K, ? extends V> m)

    a)返回的同步容器,通过将原容器包装(装饰者模式),新对象每个方法前加上Synchronized关键字。

    b)方法可以有第二个参数,自己设置锁对象

 

 

 4)Collections可利用现有容器生成检查容器  

  //传入任何Collection子类,返回一个检查Collection对象
  public static <E> Collection<E> checkedCollection(Collection<E> c,Class<E> type)
  //传入ArrayList、LinkedList ,返回检查的List
  public static <E> List<E> checkedList(List<E> list, Class<E> type)
  //传入HashSet ,返回检查Set
  public static <E> Set<E> checkedSet(Set<E> s, Class<E> type)
  //传入TreeSet ,返回检查SortedSet
  public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,Class<E> type)
   //传入HashMap ,返回检查Map
  public static <K, V> Map<K, V> checkedMap(Map<K, V> m,Class<K> keyType,alueType)
  //传入TreeMap ,返回检查SortedMap
  public static <K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K, V> m,Class<K> keyType,Class<V> valueType)

    a)返回的检查容器,通过将原容器包装(装饰者模式),在对象新增等时,对传入的对象进行类型检查

 b)第二参数就是传入参数必须要满足的类型

    c)功能出现的原因:可能将错类型带到泛型集合中。

		List<String> list = new ArrayList<String>(Arrays.asList("数组"));
		List obj = list;
		obj.add(new Date());//list中存在了一个非String类型,程序执行到这里不会报错

    d)解决方案

		List<String> list = new ArrayList<String>(Arrays.asList("数组"));
		List<String> safeList = Collections.checkedList(list, String.class);
		List obj = safeList;
		//检查容器视图受限于虚拟机可运行的运行时检查
		obj.add(new Date());//只有执行到这一步才会抛出java.lang.ClassCastException

 

 

  5)Collections、Arrays排序

//Collections只对List排序		
public static <T extends Comparable<? super T>> void sort(List<T> list)
public static <T> void sort(List<T> list, Comparator<? super T> c)

     a)上面是Collections中方法,可对ArrayList、LinkedList 进行排序。默认升序排列

     c) 降序可在第二个参数中传入Collections.reverseOrder()   

     b)排序过程:先将List生成一个数组,通过Arrays.sort()对数组进行排序。然后将数组重新写入

                           集合List中。

    public static <T extends Comparable<? super T>> void sort(List<T> list) {
        Object[] a = list.toArray();
        Arrays.sort(a);
        ListIterator<T> i = list.listIterator();
        for (int j=0; j<a.length; j++) {
            i.next();
            i.set((T)a[j]);
        }
    }

   

    c)Arrays.sort()可以对各种类型数组进行排序,当然对象要先实现Comparable接口。也可将

         Comparator作为参数传入

    d)用上面方法对List排好序后,可用Collections.binarySearch()方法进行二分查找

    e)看个栗子

	public static void main(String[] args) {

		List<Integer> list = new ArrayList<Integer>(Arrays.asList(3, 2, 5, 6,
				1, 4));
		System.err.println(list);// [3, 2, 5, 6, 1, 4]

		// 升序
		Collections.sort(list);
		System.err.println(list);// [1, 2, 3, 4, 5, 6]

		// 降序
		Collections.sort(list, Collections.reverseOrder());
		System.err.println(list);// [6, 5, 4, 3, 2, 1]

		// 自己写的排序条件
		Comparator<Integer> compare = new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 - o2; // 升序
			}
		};
		// 升序
		Collections.sort(list, compare);
		System.err.println(list);// [1, 2, 3, 4, 5, 6]

		// 二分查找
		int i = Collections.binarySearch(list, 5);
		System.err.println(i); // 4
	}

  

 

使用Abstract类

       a) java.util容器都有自己的抽象类,他们提供了该容器的部分实现,如果想创建定制的Collection

             和Map实现,可以继承抽象类,实现那些产生想要的容器所必须的方法。

       b)创建一个只读的Map,可以继承AbstractMap并实现entrySet(),其返回一个Entry的set集合

       c)创建一个只读的set,可以继承AbstractSet并实现iterator()和size()。

       d)以上的put都会抛出UnsupportedOperationException,表示不支持的请求操作。remove都是通过

             set的迭代器实现的,设计时可讲remove也抛出上面异常

       e) 通过AbstractList创建一个只读的List,必须实现get()和size()。其他add、set、reomove都会抛出上

           面异常。

 

compareTo() 和 equals()

        a)当重写equals并实现Comparable接口时,要保证一致的自然顺序。

        b)如果equals()对于某个特定的值产生true,那么compareTo()对于该比较应该返回0

        c)如果equals()对于某个特定的值产生false,那么compareTo()对于该比较应该返回非0

 

hashCode散列码   

     a)hashCode() 只有在这个类会被置于散列集合HashSet,LinkedHashSet,HashMap,linkedHashMap 

         (Map中放在key位置)才是必须的。

     b)要想使hashCode() 实用,哈希算法必须速度快,并且必须有意义,也就是说,他必须基于对象的

           内容生成的散列码(相同内容对象,生成的hashcode相同)。

     c)对象散列码意义,容器会通过对象散列码,计算出其在容器中的位置,进行快速查找。

     d)散列码不必须是独一无二的(不同内容的对象可以生成相同的散列码,但是好的hashCode() 应该

           产生分布均匀的散列码),应该更关注生成速度,而不是唯一性,但是通过hashCode() 和equals(),

           必须能够完全确定对象身份

     e)根据散列集合的数据结构,首先用对象的散列码算出对象在容器中的位置,如果两个对象计算出相

          同的存储位置,就通过equals()比较是否相等。   

     f )如果不覆盖hashCode()和equals(),那么使用散列结构就无法正确处理你的键。

     g)对于良好的编程风格而言,应该在覆盖equals()方法时,总是同时覆盖hashCode()方法。

     h)重写时要遵循一定的规则比如,hashCode()相等equals()不一定返回true,hashCode()不相等

          equals()一定返回false,equals()返回ture那么hashCode()一定相等,,,,,,,,

     i)默认的Object.hashCode()是跟据对象所在内存地址计算出的一串数字,都不相等。

          默认的Object.equals()比较的是内存地址。所以对象用在Hash集合中时都需要重写。

     j)Hash集合就是使用对象的hashCode()计算出对象的存储位置,来取代对键的缓慢搜索。

 

你可能感兴趣的:(Collections,Arrays,HashCode)