zoukankan      html  css  js  c++  java
  • java基础_集合

    1   集合概述:

    1.1,为什么出现集合?

    面向对象语言的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

    1.2,数组和集合类同是容器,有何不同?

    数组虽然也可以存储对象,但长度是固定的,集合长度是可变的数组中可以存储基本数据类型,集合只能存储对象,

    1.3,集合类的特点:

    集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

    1.4,Collection的一些方法

    Collection接口Collection接口是List和Set和Queue接口的父接口,该接口里定义的方法既可以 操作Set集合。

    也可以用于操作List集合,所以我们要先学习一下Collection里的基本方法:


    1、添加元素

            add(Objectobj); //add方法的参数类型是Object。以便于接收任意类型对象。

    2、删除元素

            remove(Objectobj);

            removeAll(另一集合);//调用者只保留另一集合中没有的元素。

            clear();//清空集合

    3、判断元素

            contains(Objectobj);//判断是否存在obj这个元素

            isEmpty();//是否为空

    4、获取个数,集合长度

            size();

    5、取交集

            retainAll(另一集合);//调用者只保留两集合的共性元素。


    1.5集合元素的获取

    当使用System.out的println方法来输出集合对象时,将输出[ele1,ele2,....]的形式,显然是因为所有的Collection实现类都重写了toString()方法但是如果想依次访问集合里的每一个元素,则需要使用某种方式来遍历集合对象,使用Iterator接口遍历集合对象或者使用foreach循环遍历集合元素。


    注意在没有限定泛型时,我们把一个对象放进集合里,集合会忘记这个对象的类型,集合会把所有的元素当成Object类的实例进行处理。

    1,使用Iterator接口(在迭代时,只能用迭代器的方法操作元素)

    Iterator接口里定义了3个方法。

    boolean hasNext();判断集合是否有下一个元素

    E next();返回集合的下一个元素

    void remove();删除集合里上一次next方法返回的元素

    class IteratorTest
    {
    	public static void main(String[] args) 
    	{
    		ArrayList al = new ArrayList();
    		al.add("java01");//add(Object obj);
    		al.add("java02");
    		al.add("java03");
    		al.add("java04");
    		Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。
    
    		while(it.hasNext())
    		{
    			//it.next()方法返回的数据类型是Object类型。需要强制类型转换
    			String s = (String)it.next();
    			if(s.equals("java02"))
    			{
    				sop(s);
    				it.remove();
    				//s.remove("java02") ,使用Iterator迭代过程中,不可修改集合元素,否则引起java.util.ConcurrentModificationException异常。
    			}
    		}
    	}
    }

    Iterator仅用于遍历集合,Iterator本身并不提供盛装对象的能力,如果需要创建Iterator对象,则必须有一个被迭代的集合。


    2使用foreach循环

    class IteratorTest 
    {
    	public static void main(String[] args) 
    	{
    		ArrayList al = new ArrayList();
    		al.add("java01");//add(Object obj);
    		al.add("java02");
    		al.add("java03");
    		al.add("java04");
    		for(Object obj : al)
    		{
    			String s = (String)obj;
    			System.out.println(s);
    			if(s.equals("java02"))
    			{
    				//ad.remove(s);引发异常
    			}
    		}
    	}
    }
    


    2  List集合

    2.1,List的特点:

    |--List:元素是有序的,元素可以重复,因为该集合体系有索引。
    |--ArrayList;底层的数据结构使用的是数组结构。特点:查询速度快,但是增删慢。线程不同步(默认长度10 )
    |--LinkedList;底层使用的是链表数据结构。   特点:增删速度很快,查询稍慢。
    |--Vector;    底层是数组数据结构   线程同步。被ArrayList替代了。

     

    2.2,List的特有方法:凡是可以操作操作角标的方法都是该体系特有的方法。

    1、增

            booleanadd(index,element);//指定位置添加元素

            BooleanaddAll(index,Collection);//在指定位置增加给定集合中的所有元素,若省略位置参数,则在当前集合的后面依次添加元素

    2、删

            Booleanremove(index);//删除指定位置的元素

    3、改

            set(index,element);//修改指定位置的元素。

    4、查

            get(index);//通过角标获取元素

            subList(from,to);//获取部分对象元素

    5、其他

            listIterator();//List特有的迭代器

            indexOf(obj);//获取元素第一次出现的位置,如果没有则返回-1

     


    注意:当调用List的set(index,Elements)方法来改变List集合索引处的元素时,指定的索引必须是List集合的有效索引.
    例如集合长度为4,就不能指定替换索引为4处的元素。


    扩展:List集合可以根据位置索引来访问集合中的元素,因此List增加了一种新的遍历集合元素的方法:使用普通的for循环来遍历集合元素。
    class ForTest
    {
    	public static void main(String[] args) 
    	{
    		ArrayList al = new ArrayList();
    		//1,添加元素。
    		al.add("java01");//add(Object obj);
    		al.add("java02");
    		al.add("java03");
    		al.add("java04");
    		for(int x= 0; x<al.size();x++)
    		{
    			System.out.println("al("+x+")="+al.get(x));
    		}
    	}
    }


    2.3,List_equals():


    注意:List判断两个对象相等只要通过equals()方法比较返回true即可。(contains(),remove(),indexOf(),等方法都会自动调用equals()方法)。
    所以在将一个对象存进List集合里时,复写其equals()方法,是非常有必要的。

    练习(List_equals复写)将自定义对象作为元素存到ArrayList集合中,并去除重复元素。

    比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。
    class Person
    {
    	private String name;
    	private int age;
    	Person(String name, int age)
    	{
    		this.name = name;
    		this.age = age;
    	}
    	public String getName()
    	{
    		return name;
    	}
    	public int getAge()
    	{
    		return age;
    	}
    	public boolean equals(Object obj)//自动被调用
    	{
    		if(!(obj instanceof Person))
    			return false;
    
    		Person p = (Person)obj;
    		System.out.println(this.name+"........"+p.name);
    
    		return this.name.equals(p.name) && this.age == p.age;
    	}
    }
    class ArrayListTest2 
    {
    	public static void sop(Object obj)
    	{
    		System.out.println(obj);
    	}
    	public static void main(String[] args) 
    	{
    		ArrayList al = new ArrayList();
    		al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30;)
    		al.add(new Person("lisi02",32));
    		al.add(new Person("lisi03",33));
    		al.add(new Person("lisi04",35));
    
    		//al = singleElements(al);
    		sop("remove 03:"+al.remove(new Person("lisi03",33)));//需要用到判断,所以要写equals()方法。返回true
    
    		Iterator it = al.iterator();
    		while(it.hasNext())
    		{
    			
    			Person p = (Person)it.next();//做强制转换。it.next是Object类型的,不认识getName()方法。所以要做强制转化
    			sop(p.getName()+"::"+p.getAge());
    		}
    	}
    	public static ArrayList singleElements(ArrayList al)
    	{
    		//定义一个临时容器。
    		ArrayList newal = new ArrayList();
    		Iterator it = al.iterator();
    
    		while(it.hasNext())
    		{
    			Object obj = it.next();
    
    			if(!newal.contains(obj))//底层自动调用equals()方法,obj调用自身的equals的方法,和newal的各个元素进行比较
    				newal.add(obj); 
    		}
    		return newal;
    	}
    }
    


    2.4,List_listIterator()

    List还额外提供了一个listIterator()方法,返回一个ListIterator对象,提供了专门操作List的方法。在listIterator接口基础上增加了如下方法。

    ->boolean hasPrevious();返回该迭代器关联的集合是否有上一个元素。
    ->Object previous();返回该迭代器的上一个元素。
    ->void add();在指定位置插入一个元素。

     

    2.5,linkedList

     
    linkedList的特有方法
    1,添加元素
    addFirst();
    addLast();

    2,获取元素但不删除元素。如果集合中没有元素,会出现异常。NoSuchElementException
    getFirst();
    getLast();

    3获取元素,并删除元素。如果集合中没有元素,会出现异常。
    removeFirst();
    removeLast();

    在JDK1.6出现了替代方法。
    1,添加元素
    offerFirst();
    offerLast();
    获取元素但不删除元素。如果集合中没有元素,会返回null
    peekFirst();
    peekLast();

    获取元素,并删除元素。如果集合中没有元素,会返回null
    pollFirst();
    pollLast();

    2.练习(LinkedList)

    例:使用LinkedList模拟一个队列或者其他数据结构。
    import java.util.*;
    class DuiLie
    {
    	private LinkedList link;
    	DuiLie()
    	{
    		link = new LinkedList();
    	}
    	public void myAdd(Object obj)
    	{
    		link.addFirst(obj);
    	}
    	public Object myGet()
    	{
    		return link.removeLast();
    	}
    	public boolean isNull()
    	{
    		return link.isEmpty();
    	}
    }
    class  LinkedListTest
    {
    	public static void sop(Object obj)
    	{
    		System.out.println(obj);
    	}
    	public static void main(String[] args) 
    	{
    		DuiLie dl = new DuiLie();		dl.myAdd("java01");
    		dl.myAdd("java02");
    		dl.myAdd("java03");
    		dl.myAdd("java04");
    
    		while(!dl.isNull())
    		{
    			sop(dl.myGet());
    		}
    	}	
    }
    

    3 Set集合

    3.1Set集合特点

    |--Set:元素师无序(存入和取出的顺序不一定一致),元素不可以重复。元素值可以是null(只有一种取出方式迭代器。)
    |--HashSet:底层数据结构是哈希表。线程不是同步的。
    |--TreeSet:底层数据结构是二叉树。可以对Set集合中的元素进行排序。

    3.2HashSet

    元素的唯一性是通过元素的两个方法,hashCode和equals来完成。

    1,如果元素的HashCode(存放位置)值相同,才会判断equals(对象本身)是否为true
    2,如果元素的Hashcode值不同,不会调用equals。
    hashcode()一样,equals()不一样也存得进去。(在同一个位置,以链的方式存储)

    注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的HashCode和equals方法。

    (set集合的方法和Colletion接口是一致的。)

    练习:HashSet_HashCode() and equals()

    例:往HashSet集合中 存入自定对象。
    姓名和年龄相同视为同一个人,重复元素。
    class HashSetTest 
    {
    	public static void main(String[] args) 
    	{
    		HashSet hs = new HashSet();
    		hs.add(new Person("a1",11));
    		hs.add(new Person("a2",12));
    		hs.add(new Person("a3",13));
    		hs.add(new Person("a2",12));
    			//先算一下new Person("a1",12);的hashcode值,和hs里的a2一样,就调用自身的equals()方法。
    		hs.remove(new Person("a3",13));
    		Iterator it = hs.iterator();
    		
    		while(it.hasNext())
    		{
    			Person p =(Person)it.next();
    			sop(p.getName()+":;"+p.getAge());
    		}
    	}
    	public static void sop(Object obj)
    	{
    		System.out.println(obj);
    	}
    }
    class Person
    {
    	private String name;
    	private int age;
    	Person(String name, int age)
    	{
    		this.name = name;
    		this.age = age;
    	}
    	public int hashCode()//复写哈希值使equals运行。
    	{
    		System.out.println(this.name+" .....hashcode")
    		return name.hashCode()+age;
    	}
    	public String getName()
    	{
    		return name;
    	}
    	public int getAge()
    	{
    		return age;
    	}
    	public boolean equals(Object obj)
    	{
    		if(!(obj instanceof Person))
    			return false;
    		Person p = (Person)obj;
    		System.out.println(this.name+"....equals...."+p.name);
    		/*
    		a2...equals..a1
    		a3...equals..a2
    		a3...equals..a1
    		a2...equals..a3
    		a2...equals..a2
    		*/
    		return this.name.equals(p.name) && this.age==p.age;
    	}	
    }
    


    3.3TreeSet

    保证元素唯一性的依据。compareTo方法return 0.

    3.3.1TreeSer排序的第一种方式:

    让元素自身具备比较性。
    元素需要实现Comparable接口,覆盖compareTo方法。
    这种方式也称为元素的自然顺序,或者默认顺序。

    3.3.2TreeSet的第二种排序方式。

    当元素自身不具备比较性,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性,在集合初始化时,就有了比较性。
    定义了比较器,实现Comparator接口,覆盖compare方法,将比较器对象作为参数传递给TreeSet集合的构造函数。

    当两种排序都存在时,以比较器为主。

    练习(TreeSet排序):往TreeSet存入自定义对象学生

    想按照学生的年龄进行排序。
    (往TreeSet存储的对象都要具备计较性。)
    记住:排序时,当主要条件相同时,一定要判断一下次要条件。
    class TreeSetDemo 
    {
    	public static void main(String[] args) 
    	{
    		TreeSet ts = new TreeSet();
    		//将自定义的比较器传给TreeSet的构造器
    		//TreeSet ts = new TreeSet(new MyCompare());
    		ts.add(new Student("lisi02",22));
    		ts.add(new Student("lisi07",20));//07存进来的时候,调用自己的compareTo和02比较
    		//没有实现comparable接口会Student cannot be cast to java.lang.Comparable 
    		ts.add(new Student("lisi09",19));//09存进来的时候,调用自己的compareTo分别和02,07比较。
    		ts.add(new Student("lisi01",40));
    
    		Iterator it = ts.iterator();
    		while(it.hasNext())
    		{
    			Student stu = (Student)it.next();
    			System.out.println(stu.getName()+"....."+stu.getAge());
    		}
    	}
    }
    class Student implements Comparable //该接口强制让学生具备比较性。
    {
    	private String name;
    	private int age;
    
    	Student(String name, int age)
    	{
    		this.name = name;
    		this.age = age;
    	}
    	public int compareTo(Object obj)
    	{
    		if(!(obj instanceof Student))
    			throw new RuntimeException("不是学生对象")
    		Student s = (Student)obj;
    		if(this.age>s.age)
    			return 1;
    		if(this.age==s.age)
    		{
    			return this.name.compareTo(s.name);
    		}
    		return -1;		
    	}
    	public String getName()
    	{
    		return name;
    	}
    	public int getAge()
    	{
    		return age
    	}
    }
    //当元素自身不具备比较性,或者具备的比较性不是所需要的。
    //这时需要让容器自身具备比较性。
    //定义了比较器,实现Comparator接口,覆盖compare方法,将比较器对象作为参数传递给TreeSet集合的构造函数
    class MyCompare implements Comparator//两个对象被集合比。。
    {
    	public int compare(Object o1,Object o2)
    	{
    		Student s1 = (Student)o1;
    		Student s2 = (Student)o2;
    
    		
    		int num = s1.getName().compareTo(s2.getName());//(String已经实现了Comparator)
    	
    		if(num==0)//主条件相同判断次要条件。 
    		{	 
    			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
    		}
    		return num;
    	}
    }

    4Map集合

    4.1Map集合特点

    Map集合:该集合存储键值,,一对一对往里存。而且要保证键的唯一性。

    |--Hashtable:底层是哈希表数据结构,不可以存入null键null值集合式线程同步的。
    用作键的对象必须实现equals()和hashcode()方法。
    |--HashMap:底层是哈希表数据结构,并允许使用null值和null值,该集合是不同步的。
    |--TreeMap:底层是二叉树数据结构。线程是不同步。可以用于给Map集合中的键排序。

    注意:其实,Set集合底层就是使用了Map集合。
    (Map提供了一个Entry内部类来封装key-value对,而计算Entry存储时只考虑Entry封装的key,从java源码来看,java
    是先实现了Map,然后通过包装一个所有vanlue都为null的Map就实现了Set集合)

    4.2Map接口常用方法。

    1、添加

            Vput(K key,V value);//添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。

            voidputAll(Map <? extends K,? extends V> m);//添加一个集合

    2、删除

            clear();//清空

            Vremove(Object key);//删除指定键值对

    3、判断

            containsKey(Objectkey);//判断键是否存在

            containsValue(Objectvalue)//判断值是否存在

            isEmpty();//判断是否为空

    4、获取

            Vget(Object key);//通过键获取对应的值

            size();//获取集合的长度

            Collection<V>value();//获取Map集合中所以得值,返回一个Collection集合

    5,,两个关于取出的方法

            Set<Map.Entry<K,V>>entrySet();返回该Map中所有key组成的Set集合。

            Set<K>  keySet();返回该Map中包含的key-value对所组成的Set集合,每个集合元素都是Map.Entry对象。

    注:HashMap集合可以通过get()方法的返回值来判断一个键是否存在,通过返回null来判断。

     

    -
    4.3map集合的两种取出方式

    1,Set<k> keySet;将map中所有的键存入到Set集合,因为Set具备迭代器,
    所以可以通过迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。


    2,Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了Set集合中。
    而这个关系的数据类型就是:Map.Entry

    练习(map_keySet and entrySet):

    两种方法的用法:

    class MapDemo2
    {
    	public static void main(String[] args) 
    	{
    		Map<String,String> map = new HashMap<String,String>();
    		map.put("002","zhangsan2");
    		map.put("003","zhangsan3");
    		map.put("001","zhangsan1");
    		map.put("004","zhangsan4");
    	
    		public static void mehod_1(HashMap<String,String> map)
    		{
    			//将map集合中的映射关系取出,存入到Set集合中,
    			Set<Map.Entry<String,String>> entrySet = map.entrySet();	
    			Iterator<Map.Entry<String,String>> it = entrySet.iterator();
    			while(it.hasNext())
    			{
    				Map.Entry<String,String> me = it.next();
    				String key = me.getKey();
    				String value = me.getValue();
    				System.out.println(key+":"+value);
    			}
    		}
    		public static void method_2(HashMap<String,String> map)
    		{
    			//先获取map集合中的所有键的Set集合,keyset();
    			Set<String> keySet = map.keySet();
    			//有了Set集合就可以获取其迭代器了。
    			Iterator<String> it = keySet.iterator();
    			while(it.hasNext())
    			{
    				String key = it.next();
    				// 有了键就可以通过map集合的get方法获取其对应的值。
    				String value = map.get(key);
    				System.out.println("key:"+key+",valur:"+value);
    			}
    		}		
    	}
    }

    练习(Map):

    "sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

    希望打印结果:a(1)c(2).......

    import java.util.*;
    class MapTest3
    {
    	public static void main(String[] args) 
    	{
    		String s = charCount("sdfgzxcvasdfxcvdf");
    		System.out.println(s);	
    	}
    	public static String charCount(String str)
    	{
    		char[] chs = str.toCharArray();
    
    		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
    		
    		int count = 0;
    
    		for(int x=0; x<chs.length; x++)
    		{
    
    			if(!(chs[x]>='a'&& chs[x]<='z'|| chs[x]>='A'&& chs[x]<='Z'))
    				continue;
    
    			Integer value = tm.get(chs[x]);//返回值
    			if(value!=null)
    				count = value;
    			count++;
    			tm.put(chs[x],count);
    			count = 0;
    
    		StringBuilder sb = new StringBuilder();
    		Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
    		Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();
    		while(it.hasNext())
    		{
    			Map.Entry<Character,Integer> me = it.next();
    			Character ch = me.getKey();
    			Integer value = me.getValue();
    			sb.append(ch+"("+value+")");
    		}
    		return sb.toString();
    	}
    }



  • 相关阅读:
    简单工厂、工厂方法和抽象工厂的学习笔记
    单一职责原则,开-闭原则,依赖倒置原则
    我对面向对象设计的理解——Java接口和Java抽象类
    高可用与负载均衡的区别
    应用交付、负载均衡(Load balancing)、高可用、F5
    四种常见的 POST 提交数据方式
    Git fetch和git pull的区别
    苹果Mac OS X显示隐藏文件的方法
    Appium教程---Client/Server Architecture
    UNIX网络编程——使用线程的TCP回射服务器程序
  • 原文地址:https://www.cnblogs.com/grkbeyond/p/4147265.html
Copyright © 2011-2022 走看看