Java基础06——集合

------- android培训java培训、期待与您交流! ----------

集合类的由来: 对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。就使用集合容器进行存储。

集合特点

1,用于存储对象的容器。

2,集合的长度是可变的。

3,集合中不可以存储基本数据类型值。

集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。

框架的顶层Collection接口:

Collection的常见方法

1,添加。

boolean add(Object obj):

boolean addAll(Collection coll):

2,删除。

boolean remove(object obj):

boolean removeAll(Collection coll);

void clear();

3,判断:

boolean contains(object obj):

boolean containsAll(Colllection coll);

boolean isEmpty():判断集合中是否有元素。

4,获取:

int size():

Iteratoriterator():取出元素的方式:迭代器。 该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。 所以该迭代器对象是在容器中进行内部实现的。

对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可, 也就是iterator方法。

Iterator接口就是对所有的Collection容器进行元素取出的公共接口。 

5,其他:

boolean retainAll(Collection coll);取交集。

Object[] toArray():将集合转成数组。

List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。

List:特有的常见方法:有一个共性特点就是都可以操作角标。

1,添加

void add(index,element);

void add(index,collection);

2,删除;

Object remove(index):

3,修改:

Object set(index,element);

4,获取:

Object get(index);

int indexOf(object);

int lastIndexOf(object);ListsubList(from,to);

list集合是可以完成对元素的增删改查。

List:

|--Vector:内部是数组数据结构,是同步的。增删,查询都很慢!

|--ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。

|--LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。


LinkedList:

addFirst();addLast():

 jdk1.6  offerFirst(); offetLast();

getFirst();.//获取但不移除,如果链表为空,抛出NoSuchElementException. getLast();

jdk1.6  peekFirst();//获取但不移除,如果链表为空,返回null.peekLast():

removeFirst();//获取并移除,如果链表为空,抛出NoSuchElementException. removeLast();

jdk1.6 pollFirst();//获取并移除,如果链表为空,返回null. pollLast();

Set:元素不可以重复,是无序。

Set接口中的方法和Collection一致。


HashSet: 内部数据结构是哈希表 ,是不同步的。

如何保证该集合的元素唯一性呢?

是通过对象的hashCode和equals方法来完成对象唯一性的。如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。 如果对象的hashCode值相

同,那么要再次判断对象的equals方法是否为true。 如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。

记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。 一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,

hashCode方法建立对象判断是否相同的依据。


TreeSet:可以对Set集合中的元素进行排序。是不同步的。

判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。

TreeSet对元素进行排序的方式一:让元素自身具备比较功能,元就需要实现Comparable接口。覆盖compareTo方法。

如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?

可以使用TreeSet集合第二种排序方式二:让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。 将该类对象作为参数传递给TreeSet集合的构

造函数。

哈希表确定元素是否相同 if(this.hashCode()== obj.hashCode() && this.equals(obj))

1,判断的是两个元素的哈希值是否相同。 如果相同,在判断两个对象的内容是否相同。

2,判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。 注意:如果哈希值不同,是不需要判断equals。

TreeSet例子:

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">* 创建了一个根据Person类的name进行排序的比较器。
 */

public class ComparatorByName implements Comparator {

	public int compare(Object o1, Object o2)
	{
		Person p1 = (Person) o1;
		Person p2 = (Person) o2;
		int temp = p1.getName().compareTo(p2.getName());
		return temp==0?p1.getAge()-p2.getAge():temp;
	}
}</span></span></span>

比较的另一种方法即让对象实现Comparable接口,即让对象本身具备可比较性并重写compareTo()方法,但不如实现Comparator接口灵活。

如下例:

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class Person implements Comparable<Object> {
	private String name;
	private int age;

	public Person() {
		super();
	}

	public Person(String name, int age) {
		super();
		this.age = age;
		this.name = name;
	}

	public int hashCode() {
		return name.hashCode() + age * 27;
	}

	// 两元素先后排序规则
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!(obj instanceof Person))
			throw new ClassCastException("类型错误");
		Person p = (Person) obj;
		return this.name.equals(p.name) && this.age == p.age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String toString() {
		return name + ":" + age;
	}

	public int compareTo(Object o) {
		Person p = (Person) o;
		int temp = this.age - p.age;
		return temp == 0 ? this.name.compareTo(p.name) : temp;
	}
}</span></span></span>


泛型

在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。

当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。其实<>就是一个用于接收具体引用数据类型的参数范围。

泛型技术是给编译器使用的技术,用于编译时期。运行时会将泛型去掉,生成的class文件不带泛型,即泛型的擦除(为了兼容运行的类加载器)

在运行时,通过获取元素的类型进行转换动作,不用使用者强制转换,即泛型的补偿。

好处:1.将运行时期的问题ClassCastException转到了编译时期。2.避免了强制转换的麻烦

 可以对类型进行限定:

? extends E:接收E类型或者E的子类型对象。上限!

 一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患。

? superE :接收E类型或者E的父类型。下限!

常对出操。比如比较器


集合的一些技巧:

需要唯一吗? 

需要:Set

需要制定顺序:

需要: TreeSet

不需要:HashSet 但是想要一个和存储一致的顺序(有序):LinkedHashSet

不需要:List

需要频繁增删吗?

需要:LinkedList

不需要:ArrayList

array:就要想到数组,就要想到查询快,有角标.

link:就要想到链表,就要想到增删快,就要想要 add get remove+frist last的方法

hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。

tree:就要想到二叉树,就要想要排序,就要想到两个接口Comparable,Comparator 。


Map:一次添加一对元素。Collection 一次添加一个元素。Map也称为双列集合,Collection集合称为单列集合。

其实map集合中存储的就是键值对。map集合中必须保证键的唯一性。

常用方法:

1,添加。

value put(key,value):返回前一个和key关联的值,如果没有返回null.

2,删除。

void  clear():清空map集合。

valuere move(key):根据指定的key翻出这个键值对。

3,判断。

boolean containsKey(key):

boolean containsValue(value):

boolean isEmpty();

4,获取。

valueget(key):通过键获取值,如果没有该键返回null。

当然可以通过返回null,来判断是否包含指定键。

int size(): 获取键值对的个数。

Map常用的子类:

|--Hashtable :内部结构是哈希表,是同步的。不允许null作为键,null作为值。

|--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。

|--HashMap: 内部结构是哈希表,不是同步的。允许null作为键,null作为值。

|--TreeMap: 内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。


Map方法演示:

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class MapDemo {

	public static void main(String[] args) {

		Map<Integer, String> map = new HashMap<Integer, String>();
		method_2(map);
	}

	public static void method_2(Map<Integer, String> map) {
		map.put(8, "zhaoliu");
		map.put(2, "zhaoliu");
		map.put(2, "zhaoliu");
		map.put(6, "wangcai");
		/*
		 * 方法一:通过Map转成Set可以迭代
		 * 利用方法entrySet,将键和值的映射关系作为对象存储到Set集合中,其类型是Map.EntrySet
		 */
		Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
		Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
		while (it.hasNext()) {
			Map.Entry<Integer, String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key + "::" + value);
		}
		/*
		 * 方法二:取出map中所有元素 通过keySet方法获取map中所有的键所在的Set集合,再通过Set的迭代器获取每个键值
		 * 再对每一个键通过map集合的get方法获取对应的值就可
		 */
		Set<Integer> keySet = map.keySet();
		Iterator<Integer> it2 = keySet.iterator();
		while (it2.hasNext()) {
			Integer key = it2.next();
			String value = map.get(key);
			System.out.println(key + ":" + value);
		}

	}

}</span></span></span>

TreeMap实例:

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">/*
 * 获取字符串中每一个字母出现的次数
 * 思路:
 * 字母和次数之间存在映射关系,考虑用Map集合
 * 为保证顺序排列,用TreeMap集合
 * 1.操作的是字符串的字母,先将字符串变成字符数组
 * 2.遍历字符数组,用每个字母作为键去查Map集合
 * 3.如果该字母键不存在,则将该字母作为键,值为1存储到Map集合
 * 4.如果该字母键存在,则将该字母键对应值取出并+1,再将该字母和值存储到Map集合,键相同值会覆盖。
 * 5.便利结束
 */
public class MapTest {

	public static void main(String[] args) {
		String str = "fdg+avAdc	bs5dDa9c-dfs";
		String s = getCharCount(str);
		System.out.println(s);
	}

	public static String getCharCount(String str) {
		char[] chs = str.toCharArray();
		Map<Character, Integer> map = new TreeMap<Character, Integer>();
		for (int i = 0; i < chs.length; i++) {
			if (!(Character.toLowerCase(chs[i]) >= 'a' && Character
					.toLowerCase(chs[i]) <= 'z'))
				continue;
			Integer value = map.get(chs[i]);
			int count = 1;
			if (value != null) {
				count = value + 1;
			}
			map.put(chs[i], count);
		}
		return mapToString(map);
	}

	private static String mapToString(Map<Character, Integer> map) {
		StringBuilder sb = new StringBuilder();
		Iterator<Character> it = map.keySet().iterator();
		while (it.hasNext()) {
			Character key = it.next();
			Integer value = map.get(key);
			sb.append(key + "(" + value + ")");
		}
		return sb.toString();
	}
}</span></span></span>

Map集合与Collection集合的区别

1. Map中一次存储是键值对,Collection中一次存储是单个元素

2. Map的存储使用put方法,Collection存储使用的是add方法

3. Map的取出,得将Map转成Set,再使用迭代器取出,Collection的取出,直接使用迭代器

4. 如果对象很多,必须使用容器存储,如果元素存在映射关系,优先考虑使用Map存储或数组,没有映射关系,可以使用Collection存储。

Collections:它的出现给集合操作提供了更多的功能。这个类不需要创建对象,内部提供的都是静态方法。

sort方法:

Collections.sort(list);//list集合进行元素的自然顺序排序。

Collections.sort(list,new ComparatorByLen());//按指定的比较器方法排序。

public static <T extends Comparable <? super T>> void sort(List<T> list)

T必须是Comparable的子类,才具有比较性,实现comparator方法;Comparable泛型的类型可以是T的父类。

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">//Collections.sort(list, new ComparatorByLen());</span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">class ComparatorByLen implements Comparator<String>{

      public int compare(String s1,String s2){

        int temp = s1.length()—s2.length();

        return temp==0?s1.compareTo(s2):temp;

      }

    }</span></span></span>

max方法:

Collections.max(list); //返回list中字典顺序最大的元素。

public static <T extends Object & Comparable<? super T>> T max (Collection<? extends T> coll)  //根据元素的自然顺序,返回给定collections的最大元素

public static <T> T max(Collections<? extends T> coll,  Comparator<? super T> comp) //根据指定比较起产生的顺序,返回给定Collections的最大元素

其他方法:

int index = Collections.binarySearch(list,"zz");//二分查找,返回角标。

Collections.reverseOrder();//逆向反转排序。

Collections.shuffle(list);//随机对list中的元素进行位置的置换。

将非同步集合转成同步集合的方法

Collections中的  XXX synchronizedXXX(XXX);

  List synchronizedList(list);

  Map synchronizedMap(map);

  原理:定义一个类,将集合所有的方法加同一把锁后返回。

Collection 和 Collections的区别:

Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。

Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。

Arrays数组工具类

数组转集合工具静态

如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。

如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储。

List asList(数组)将数组转成集合。如:List<String> list = Arrays.asList(arr);

好处:可以使用集合的方法操作数组中元素。注意:数组的长度是固定的,对于集合的增删方法是不可以使用的,否则会发生UnsupportedOperationExceptionn

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">//toString的经典实现
	public static String myToString(int[] a)
	{
		int iMax = a.length - 1;
		if(iMax == -1)
			return "[]";
		StringBuilder sb = new StringBuilder();
		sb.append('[');
		for(int i=0; ;i++){
			sb.append(a[i]);
		if (i == iMax)
			return sb.append(']').toString();
		sb.append(", ");
		}
	}</span></span></span>
集合转数组:使用的是Collection接口的toArray方法。如:String[] arr = list.toArray(new String[list.size()]);

可以对集合中的元素操作的方法进行限定。

数组长度指定为集合的size。如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。 

如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为 null。

高级for循环

格式for(数据类型 变量名 : 被遍历的集合(Collection)或者数组){}

对集合进行遍历,只能获取集合元素,但是不能对集合进行操作。

迭代器除了遍历,还可以进行remove集合中元素的操作,如果是ListIterator,还可以在遍历过程中对集合进行增删改查的操作。

传统for循环和高级for循环区别:

传统for循环可以对语句执行很多次,因为可以定义控制循环的增量和条件

高级for循环局限(必须有被遍历的目标),建议在遍历数组时,仍然使用传统for循环,可以定义脚标。

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family: Arial;">public class ForEachDemo {</span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family: Arial;">	public static void main(String[] args) {
		ArrayList<String> al = new ArrayList<String>();
		al.add("abc1");
		al.add("abc2");
		al.add("abc3");

		for (String s : al) {
			System.out.println(s);
		}

		HashMap<Integer, String> hm = new HashMap<Integer, String>();
		hm.put(1, "a");
		hm.put(2, "b");
		hm.put(3, "c");
		Set<Integer> keySet = hm.keySet();
		for (Integer i : keySet) {
			System.out.println(i + "::" + hm.get(i));
		}
		for (Map.Entry<Integer, String> me : hm.entrySet()) {
			System.out.println(me.getKey() + "----------" + me.getValue());
		}

	}
}</span></span></span>
方法的可变参数:

数组参数的简写形式,不用每次都手动建立数组对象,只要将要操作的元素作为参数传递即可,隐式将这些参数封装成数组。注意,一定要定义在参数列表最后面。

静态导入:

其实导入的是类中的静态成员。

当类名重名时,需要指定具体的包名。当方法重名时,指定具备所属的对象或类

import Static java.util.Arrays.*   //导入的是Arrays类的所有静态成员。

<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;">import static java.lang.System.*;

public class ParamMethodDemo {
	public static void main(String[] args) {
		show("go", 2, 3, 4, 8);
	}

	public static void show(String str, Integer... arr) {
		out.println(str + ", " + arr.length);
	}
}</span></span></span>

集合框架查补遍历集合:

<span style="font-size:12px;"><span style="font-size:12px;">//遍历List方法1,使用普通for循环
		for(int i=0; i<list.size(); i++)
		{
			String temp = (String)list.get(i);
			System.out.println(temp);
		}
		//遍历List方法2,使用增强for循环
		for(String temp : list)
		{
			System.out.println(temp);
		}
		//遍历List方法3,使用Iterator迭代器
		for(Iterator<String> it = list.iterator(); it.hasNext();)
		{
			String temp = (String)it.next();
			System.out.println(temp);
		}
		//或者
		Iterator it = list.iterator();
		while(it.hasNext())
		{
			Object obj = it.next();
			it.remove();//如果要遍历删除集合中的元素,建议使用这种方式
			System.out.println(it);
		}
		//遍历Map
		Map<Integer, Person> map = new HashMap<Integer, Person>();
		Set<Integer> keySet = map.keySet();
		for(Integer id : keySet)
		{
			System.out.println(map.get(id).name));
		}</span></span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值