Java集合Collection
1.Collection详解
集合的特点:用于存储对象的容器(存储对象的引用),集合的长度是可变的,集合中不可以存储基本数据类型值
[code]/* person p = new person(); ArrayList a = new ArrayList(); al.add(p);//不表示将p这个对象放进了al这个容器里了 表示了将p这个对象的地址放进al容器里使al容器指向对象p 容器中不可能存放的是对象的实体,只能存放对象的地址 */
集合与数组的区别:
集合中可以存储任意的对象,且长度是可变的
数组中只能存储同一类型的数据,且长度是不可变的。
1.1 Collection的常用方法:
添加元素 boolean add(Object);
[code]public static void addDemo() { ArrayList a1 = new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); System.out.println(a1);//可以直接打印集合 }
删除元素 boolean remove(Object); 返回的是boolean.(List集合下也可以通过指定的角标来删除某个对象,返回的是被删除的那个对象)
[code]public static void deleteDemo() { ArrayList a1 = new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); boolean b = a1.remove("java03"); System.out.println(a1); System.out.println(b); }
清空元素:void clear();如果集合不支持该方法会抛出该异常:UnsupportedOperationException
[code]public static void clearDemo() { ArrayList a1 = new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); a1.clear(); System.out.println(a1); }
判断某元素是否存在:boolean contains(Object)
[code]public static void containsDemo() { ArrayList a1 = new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); boolean b = a1.contains("java03"); System.out.println("java03是否存在:"+b); }
获取集合中元素的个数:int size();
[code]public static void sizeDemo() { ArrayList a1 = new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); int a = a1.size(); System.out.println("size:"+a); }
判断集合是否为空:boolean isEmpty();
[code]public static void isEmptyDEmo() { ArrayList a1 = new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); boolean b = a1.isEmpty(); System.out.println("集合是否为空?:"+b); }
取交集:al1中只会保留和al2中相同的元素,如果没有交集就为空:boolean retainAll(Object)
[code]public static void retainAllDemo() { ArrayList al1 = new ArrayList(); al1.add("java01"); al1.add("java02"); al1.add("java03"); al1.add("java04"); ArrayList al2 = new ArrayList(); al2.add("java01"); al2.add("java02"); al2.add("java05"); al2.add("java06"); //boolean b = al1.retainAll(al2); //System.out.println(b); System.out.println(al1); System.out.println(al2); boolean b = al1.removeAll(al2);//把相同的删除 System.out.println(b); System.out.println(al1); }
1.2 特殊方法迭代器
取出集合中的元素:Iterator<e> iterator();(返回的是一个Iterator接口)
Iterator接口中的方法:
判断还有没有元素:boolean hasNext()
迭代下一个元素:E next();
删除元素:void remove()
[code]public static void iteratorDemo() { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java03"); al.add("java04"); /*注意: 在迭代的时候要判断一次获取一次,也就是判断一次hasNext()一次,只能next()一次 并且在迭代过程中不能使用集合的方法操作集合,会发生并发异常 */ Iterator it = al.iterator(); while(it.hasNext()){ System.out.println(it.next()); } /* 使用for可以节省空间 for (Iterator it = al.iterator(); it.hasNext();) { if(it.next().equals("java03")) it.remove(); } System.out.println(al); */ }
2 List详解
可变数组的原理:就是不断的创建新的数组,将原数组加到新的数组中
|--List:元素是有序的(怎么存的就怎么取出来,顺序不会乱),元素可以重复(角标1上有个3,角标2上也可以有个3)因为该集合体系有索引,
|-- ArrayList:底层的数据结构使用的是数组结构(数组长度是可变的百分之五十延长)(特点是查询很快,但增删较慢)线程不同步
|-- LinkedList:底层的数据结构是链表结构(特点是查询较慢,增删较快)
|-- Vector:底层是数组数据结构 线程同步(数组长度是可变的百分之百延长)(无论查询还是增删都很慢,被ArrayList替代了)
2.1 ArrayList
List:特有的方法,凡是可以操作角标的方法都是该体系特有的方法
增
boolean add(int index, E element)
boolean addAll(index,Collection)
[code]public static void List_add(){ ArrayList a1 = new ArrayList(); a1.add("java"); a1.add("php");//List集合中的元素可以重复 a1.add(".net"); System.out.println("原集合:"+a1); a1.add(1, "Flash"); a1.add(0, "ps"); System.out.println(a1); ArrayList a2 = new ArrayList(); a2.add("javascript"); a2.add("3dMax"); a2.add("IBM"); a1.addAll(0, a2); System.out.println(a1); }
删除指定位置的元素
boolean remove(int index)
[code]public static void List_remove(){ ArrayList a1 = new ArrayList(); a1.add("javascript"); a1.add("php"); a1.add("flash"); System.out.println("原集合:"+a1); a1.remove(0); System.out.println(a1); }
修改指定角标的元素 set(int index, E element) 返回的是修改的那个元素
[code]public static void List_set() { ArrayList a1 = new ArrayList(); a1.add("javascript"); a1.add("php"); a1.add(".net"); System.out.println("原集合:"+a1); a1.set(1, "falsh"); System.out.println(a1); }
查
get(int index) 返回列表中指定位置的元素
subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分元素。
[code]public static void List_get() { ArrayList a1 = new ArrayList(); a1.add("java"); a1.add("php"); a1.add("flash"); System.out.println(a1.get(0));//获取指定角标的元素,有了该方法就可以遍历该集合中的所有元素 System.out.println(a1.subList(1, 3));//获取集合中某一部分的元素,包含头不包含尾 }
List集合特有的迭代器:ListIterator(是Iterator的子接口)
注意:
在迭代时,是不可以通过集合对象的方法操作集合中的元素
因为会发生ConcurrentModificationException异常(并发异常)
所以,在迭代器时,只能用迭代器的方法造作元素
因为Iterator方法是有限的所以只能对元素进行判断,取出,删除的操作
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator
该接口只能通过List集合的listIterator方法获取
[code]public class ListIteratorDemo { public static void main(String[] args) { ArrayList a1 = new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); System.out.println("原集合是:"+a1); /*在迭代过程中准备添加或者删除元素 Iterator it = al.iterator(); while (it.hasNext()){ Object obj = it.next(); if (obj.equals("java02")) //al.add("java008");//会出现并发异常,因为迭代器正在操作集合,不能再用集合的方法操作集合了 it.remove();//将java02的引用从集合中删除了 System.out.println("obj:"+obj); } */ //只有List的listIterator有增,删,改,查这些功能,因为只有List有索引 ListIterator li = a1.listIterator(); while (li.hasNext()){ if(li.next().equals("java02")) //li.add("java009"); li.set("java006"); } } }
Vector类和Enumeration接口:
Vector类是java语言提供的一种高级数据结构,可用于保存一系列对象,java不支持动态数组,Vector类提供了一种与动态数组相近的功能,如果我们不能预先确定要保存的对象的数目,或是需要方便获取某个对象的存放位置时,Vector类都是一个不错的选择(因为名字太长现在已经被取代)
[code]import java.io.IOException; import java.util.Enumeration; import java.util.Vector; public class Text { public static void main(String[] args) { int b = 0; Vector v = new Vector(); System.out.println("Please Enter Number:"); while(true){ try { b = System.in.read(); } catch (IOException e) { e.printStackTrace(); } if(b=='\r' || b=='\n'){ break;//break用于跳出循环和switch }else{ int num = b-'0'; v.addElement(new Integer(num)); } } int sum = 0; Enumeration en = v.elements(); while(en.hasMoreElements()){ Integer IntObject = (Integer)en.nextElement(); sum+=IntObject.intValue(); } System.out.println(sum); } }
该列子中因为不能确定用户会输入多少位数字,所以不能使用数组来存储每一个数值,所以选择集合,集合只能接受对象类型的数据
Vector:枚举就是Vector特有的取出方式,跟迭代器很像(其实枚举和迭代是一样的) 已经被迭代器取代
[code]public class VectorDemo { public static void main(String[] args) { Vector v = new Vector(); v.add("java01"); v.add("java02"); v.add("java03"); v.add("java04"); for(Enumeration en = v.elements();en.hasMoreElements();){ System.out.println(en.nextElement()); } } }
2.2 LinkedList
特有方法:
addFirst();在头部添加元素 addLast();在尾部添加元素
getFirst(); getLast(); 获取元素但不删除元素。如果集合中没有元素,会出现NoSuchElementException
removeFirst(); removeLast(); 获取元素但是删除元素。如果集合中没有元素,会出现NoSuchElementException
在JDK1.6出现了替代方法
offerFirst(); offerLast();
peekFirst(); peekLast(); 获取元素,但是元素不被删除。如果集合中没有元素,会返回null
pollFirst(); pollLast(); 获取元素,但是元素被删除。如果集合中没有元素,会返回null
[code]public class LinkedListDemo { public static void main(String[] args) { LinkedList link = new LinkedList(); link.add("java01"); link.add("java02"); link.add("java03"); link.add("java04"); while(!link.isEmpty()){ System.out.println((link.removeLast())); } } }
3 Set详解
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复,因为该集合体系没有索引。Set集合的功能Collection是一致的,取出只有一种方式 就是迭代器
----HashSet:底层数据结构是哈希表,线程是非同步的(有个子类可以实现有序,LinkedHashSet(链表结构和has结构相结合))
----TreeSet:可以对Set集合中的元素进行排序(自然排序,由小到大) 底层的数据结构是二叉树,线程不同步
3.1 HashSet集合
[code]import java.util.HashSet; import java.util.Iterator; public class HashSetDemo { public static void main(String[] args) { HashSet hs = new HashSet(); /* sop(hs.add("java01"));结果是true sop(hs.add("java01"));结果是false,因为java01已经存在了就不在存了 */ hs.add("java01"); hs.add("java02"); hs.add("java02");//返回结果为false,因为集合中已经有java02了 就不在存了 hs.add("java02"); hs.add("java03"); hs.add("java04"); //set集合的取出只有一种方式 就是迭代器 for (Iterator it = hs.iterator(); it.hasNext();) { System.out.println(it.next()); } } }
HashSet是如何保证元素的唯一性的(判断元素相同的依据): 是通过元素的两个方法,hashCode和equals来完成
-如果元素的HashCode值相同,才会判断equals是否为true
-如果元素的hashcode值不同,不会调用equals
对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法
往hashSet集合中存入自定义对象.姓名和年龄相同为同一个人,重复元素。
[code]import java.util.*; public 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)); hs.add(new Person("a4",14)); Iterator it = hs.iterator(); while (it.hasNext()){ Person p = (Person)it.next(); System.out.println(p.getName()+"::"+p.getAge()); } } } //以后开发中描述事物时,都要有复写hashCode和equals方法,因为可能这个对象会存储到HashSet集合中 class Person{ private String name; private int 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 Person(String name, int age) { super(); this.name = name; this.age = age; } //用于计算哈希值是否相等, public int hashCode(){ //return 60;//很多重复比较,导致哈希值都相同,要调用equals方法比较是不是同一个对象 return name.hashCode()+age*27;//*27是为了保证哈希值的唯一性,可以任何值都可以.每个字符串都有自己的哈希值 } //用于比较两个对象是否相等 public boolean equals(Object obj){ if (!(obj instanceof Person)) return false; Person p = (Person)obj; return this.name.equals(p.name) && this.age == p.age; } }
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。建立对象判断是否相同的依据。
LinkedHashSet(链表结构和has结构相结合)):变集合中的元素变得有序(这里说的有序不是指排序而是指怎么存的顺序跟取出来的顺序是一样的)
[code]import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; public class LinkedHashSetDemo { public static void main(String[] args) { HashSet hs = new LinkedHashSet(); hs.add("hahah"); hs.add("hehe"); hs.add("heihei"); hs.add("xixii"); hs.add("hehe"); Iterator it = hs.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
3.2 TreeSet
[code]import java.util.Iterator; import java.util.TreeSet; public class TreeSetDemo { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add("cab");//打印结果是对照字符编码表中对于的数值的大小排序 ts.add("aab"); ts.add("dab"); ts.add("Bab"); Iterator it = ts.iterator(); while (it.hasNext()){ System.out.println(it.next()); } } }
判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
TreeSet对元素进行排序的方式一:让元素自身具备比较功能,元就需要实现Comparable接口。覆盖compareTo方法。
需求:往TreeSet集合中存储自定义对象。安照人的年龄进行排序
[code]import java.util.Iterator; import java.util.TreeSet; public class TreeSetTest { public static void main(String[] args) { TreeSet ts = new TreeSet();//往TreeSet集合中的对象会自动排序的,所以往里存的对象必须要具有比较性 ts.add(new Person("jianqing",18)); ts.add(new Person("jianfeng",14)); ts.add(new Person("jianhuo",15)); ts.add(new Person("jianguang",17)); Iterator it = ts.iterator(); while (it.hasNext()){ Person p = (Person)it.next(); System.out.println(p.getName()+"...."+p.getAge()); } } } //该接口强制让学生具备比较性 class Person implements Comparable{ 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; } //实现了Compareble要覆盖该方法,这个方法在底层会自动调用,该方法可以给自定义对象进行排序 public int compareTo(Object obj){ if (!(obj instanceof Person)) throw new RuntimeException("不是人"); Person p = (Person)obj; if(this.age>p.age) return 1; if(this.age == p.age){ return this.name.compareTo(p.name);//排序时,当主要条件相同时,一定要判断下次要条件。如果这里返回0 说明两个对象是同一个对象 } return -1; } public boolean equals(Object obj){ if (!(obj instanceof Person)) return false; Person p = (Person)obj; return this.name.equals(p.name) && this.age == p.age; } }
当元素自身不具备比较性,或者具备的比较性不是所需要的(不能去改Person类的代码,有可能不是自己写的),这时需要让容器自身具备比较性
可以使用TreeSet集合第二种排序方式二:让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主(定义一个类,实现comparator接口,覆盖compare方法
[code]import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; public class TreeSetTest{ public static void main(String[] args) { TreeSet ts = new TreeSet(new MyCompare());//将比较器对象作为参数传递给TreeSet集合的构造函数。 ts.add(new Person("jianqing",18)); ts.add(new Person("jianfeng",14)); ts.add(new Person("jianhuo",15)); ts.add(new Person("jianguang",17)); Iterator it = ts.iterator(); while (it.hasNext()){ Person p = (Person)it.next(); System.out.println(p.getName()+"...."+p.getAge()); } } } class Person implements Comparable{//该接口强制让学生具备比较性 private String name; private int age; Person(String name,int age){ this.name = name; this.age = age; } public int compareTo(Object obj){//实现了Compareble后这个方法在底层会自动调用 if (!(obj instanceof Person)) throw new RuntimeException("不是人"); Person p = (Person)obj; if(this.age>p.age) return 1; if(this.age == p.age){ return this.name.compareTo(p.name); } return -1; } 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; return this.name.equals(p.name) && this.age == p.age; } } //定义一个比较器,按照姓名排序 class MyCompare implements Comparator{ public int compare(Object o1,Object o2){ Person s1 = (Person)o1; Person s2 = (Person)o2; int num = s1.getName().compareTo(s2.getName()); if(num==0){ return (new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()))); /* if(s1.getAge()>s2.getAge()) return 1; if(s1.getAge()==s2.getAge()) return 0; return -1; */ } return num; } }
4 Map集合
Map集合(双列集合):该集合存储键值对,一对一对往里存,而且要保证键的唯一性
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合 线程同步的,效率低
|--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|--HashMap:底层也是哈希表数据结构,可以存入null键null值,该集合 不同步的,效率高
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于map集合中的键进行排序
添加
put(K key,V value)
putAll(Map<? extends K,?extends V> m)
删除
clear() 清除集合中的所有键和值
remove(Object key) 传入键,删除相应的值,结果会返回相应的值
获取
get(Object key) 返回指定键的值,如果没有该键返回null
size() 返回该集合的长度
Collection values() 返回集合中的所有值并且保存到Collection集合中
判断
containsKey(Object key) 判断 该键是否存在
containsValue(Object value) 判断该值是否存在
isEmpty() 判断集合是否为空
跟Set很像,Set底层就是使用了Map集合
[code]import java.util.Collection; import java.util.HashMap; import java.util.Map; public class MapDemo { public static void main(String[] args) { Map<Integer,String> map1 = new HashMap<Integer,String>(); map1.put(1,"huangjianfeng1"); //map.put(1,"huangjianfeng1");//存相同键,值会被覆盖 map1.put(2,"huangjianfeng2"); map1.put(3,"huangjianfeng3"); map1.put(4,"huangjianfeng4"); //map.clear(); System.out.println(map1); Map<String,String> map = new HashMap<String,String>(); //添加元素 map.put("1","huangjianfeng1"); map.put("2","huangjianfeng2"); map.put("3","huangjianfeng3"); map.put("04",null);//null除了在HashTable之外,可以作为键或者值 System.out.println(map.get("04")); //删除 System.out.println(map.remove("1"));//删除1号键,并且能返回1号键对应的值,如果没有对应的键,则返回null //map.clear(); //判断 System.out.println(map.containsKey("2")); System.out.println(map.containsValue("huangjianfeng1")); //获取 System.out.println(map.get("1"));//,如果有该键,返回该键对应的值,如果没有该键 返回null System.out.println(map.size()); //获取map集合中所有的值 Collection<String> coll = map.values(); //values()方法返回的是一个Collection集合 System.out.println(coll);//用迭代 //添加元素,如果出现添加时相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值 System.out.println(map.put("1","huangjianfeng1")); System.out.println(map.put("1","huangjianfeng2")); } }
map集合中元素的取出
map集合的取出原理:将map集合转成set集合,在通过迭代器取出
map集合的第一种取出方式:Set<k> keySet:将map中所有的键存入到Set集合,因为set具备迭代器,所以可以迭代方式取出所有的键,在根据get方法,获取每一个键对应的值
[code]import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Map_KeySet { public static void main(String[] args) { Map<Integer,String> map = new HashMap<Integer,String>(); map.put(1,"huangjianfeng1"); map.put(2,"huangjianfeng2"); map.put(3,"huangjianfeng3"); //先通过该方法keySet()(返回的就是set集合)获取map集合的所有键 存到set集合中 Set<Integer> keySet = map.keySet(); //有了Set集合,就可以获取其迭代器 for (Iterator<Integer> it = keySet.iterator();it.hasNext() ; ){ Integer key = it.next(); //有了键就可以通过map集合的get方法获取对应的值 String value = map.get(key); System.out.println(key+"="+value); } } }
- java之集合Collection详解之3
- java 集合(2) 遍历collection集合方法 iterator / 加强型for循环
- Java——Collection,集合的批处理方法
- Java中的collection集合概述
- Java基础(集合卷)--单列集合老大Collection
- 集合 - Collection Java笔记总结
- Java-集合框架Collection之Set(二)
- Java Collection 集合线程安全方法
- Java中集合(Collection)的遍历以及迭代器Iterator的详解!
- Java集合(Collection)综述
- Java集合框架介绍。Java Collection Frameworks = JCF
- 【集合详解】Java集合总结(上)-Collection家族
- Java集合之Collection
- java 集合-Collection
- 迭代器模式和java集合Collection(二)HashMap和Set
- 黑马程序员——Java集合Collection
- Java基础——Collection集合分类及特点
- java集合(一)——集合框架 Collection, Map
- JAVA语言基础:集合框架Collection 和Map
- 【java集合一】根接口Collection、Map