黑马程序员-Java的集合类(java中类的容器)和算法
来源:互联网 发布:excel调用数据库 编辑:程序博客网 时间:2024/05/17 07:23
-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
Java的集合类(java中类的容器)和算法
一、集合
1、集合只用于存储对象,集合的长度是可变的,集合可以存储不同类型的对象;
2、java的数据结构:每一个容器对数据的存储方式不同,所以具有多种多样的容器;
3、集合中的分类和常用接口、类
|--Collection集合接口:一组单独的元素存储
|--List列表接口:元素是有序的(存入和取出的顺序一致),元素都有索引(角标),元素允许重复。
|--ArrayList:底层数据结构是数组,查询速度快,增删操作较慢,线程不同步
|--LinkedList:底层数据结构是链表,查询效率较低,增删操作快,线程不同步
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。
|--Set集接口:元素是无序的(存入和取出的顺序不一定一致),元素不允许重复,底层用到了Map
|--HashSet:底层数据结构是哈希表,存储的对象最好复写hashCode和equals方法,保证元素不会重复。线程不同步。
|--TreeSet:底层数据结构是二叉树,可以对Set集合中的元素按自然顺序进行排序,线程是不同步的。
存储的对象具备比较性。
|--Map映射接口:数据是以键值对的形式存储的,有的元素存在映射关系就可以使用该集合,元素不允许重复
|--HashTable:底层数据结构是哈希表,线程同步。不允许有null键或值。jdk1.0效率低;
|--HashMap:底层数据结构也是哈希表,线程不同步。允许有null键或值。将hashtable替代,jdk1.2效率高。
|--TreeMap:底层数据结构是二叉树(红-黑树)。线程不同步。可通过比较器用于给Map集合中键进行排序。
3、集合关系图
4、集合的特点
a、集合中存储的都是对象的引用(地址)。
b、add方法的参数类型是Object。以便于接收任意类型对象。
二、Collection集合接口
1、Collection定义了集合框架的共性功能。
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。
一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
2、Collection的常见方法:
a、添加:
boolean add(Object obj);
boolean addAll(Collection coll);
b、删除:
boolean remove(Object obj);
boolean removeAll(Collection coll);
void clear();
c、判断:
boolean contains(Object obj);
boolean containsAll(Collection coll);
boolean isEmpty();判断集合中是否有元素。
d、获取:
int size();
iterator();
e、其他:
boolean removeAll(Collection<?> c);取差集
boolean retainAll(Collection coll);取交集
Object toArray();将集合转成数组
三、迭代器:
1、集合是继承了public interface Iterable<T>接口的Iterator<T> iterator()方法。
2、迭代器是集合的取出元素方式,会直接访问集合中的元素,所以将迭代器通过内部类的形式来进行描述。
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同,所以该迭代器对象是在容器中进行
内部实现的,也就是iterator方法在每个容器中的实现方式是不同的。
对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,也就是iterator方法。
3、Iterator接口
Iterator iterator();
a、Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
通过容器的iterator()方法获取该内部类的对象。
b、操作方法
boolean hasNext();
E next();
void remove();
注:在迭代循环中next()一次,就必须hasNext()判断一次;连续两次调用next()可能发生错误。
import java.util.*;class CollectionDemo {public static void collectionBaseOperater(){Collection a = new ArrayList(); //增加a.add("java 01");a.add("java 02");a.add("java 03");a.add("java 04"); //删除a.remove("java 03");//a.clear(); //长度sop("a.size():"+a.size()); //是否为空sop("a.contains:"+a.contains("java 03")); sop("a.isEmpty:"+a.isEmpty()); //打印sop(a);sop("\r\n------------------------------\r\n"); //集合操作Collection a1 = new ArrayList();a1.add("java 01");a1.add("java 02");a1.add("java 03");a1.add("java 04");Collection a2 = new ArrayList();a2.add("java 01");a2.add("java 02");a2.add("java 05");a2.add("java 06");//a1.retainAll(a2);//取交集a1.removeAll(a2);//取差集sop(a1);sop(a2);}public static void printf(Collection c){/*Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。while(it.hasNext()){sop(it.next());}*/ //采用for循环,使it成为局部变量,用完就可以清除出内存,同时对象垃圾也可以回收。for(Iterator it = c.iterator();it.hasNext();){System.out.print(it.next()+" ");}System.out.println();}public static void main(String[] args) {//collectionBaseOperater();String[] strArr = {"This","is ","a","java","test."};Collection a = new ArrayList();for(int i=0;i<strArr.length;i++){a.add(strArr[i]);}printf(a);}public static void sop(Object obj){System.out.println(obj);}}
4、ListIterator类
a、ListIterator是Iterator的子接口。
在迭代操作时,不可以又通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。
b、系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。
只能用于List及其子类型。
c、操作方法
void add(E e);
boolean hasNext();
E next();//覆盖了Iterator接口的方法
void remove();
//逆向遍历,从集合的最后一个元素读取,判断前面有没有元素
boolean hasPrevious();//第一次使用的是时候为假,如果接着previous,就会发生NoSuchElementException违例,
//所以要先判断,再使用previous();
E previous();
四、List列表接口及其相关类
1、List的共性方法:特有的常见方法,有一个共性特点就是都可以操作角标。
a、添加(插入)
void add(int index,E element);
boolean addAll(int index,Collection<? extends E> c);
b、删除
E remove(int index);
boolean remove(Object o);
c、修改
E set(int index,E element);
d、获取:
E get(int index);
int indexOf(Object o);
int lastIndexOf(Object o);//获取指定元素的位置。
List<E> subList(int fromIndex,int toIndex);
ListIterator listIterator();
2、ArrayList类*
(1)动态数组的数据结构,默认长度为10,当超过时50%延长,而Vector是100%延长。
(2)ArrayList类与List接口中方法基本一致。
(3)ArrayList和LinkedList的大致区别:
a、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
b、对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
c、对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据
import java.util.*;class ListDemo {public static void sop(Object obj){System.out.println(obj);}public static void printf(Collection c){for(Iterator it = c.iterator();it.hasNext();){System.out.print(it.next()+" ");}System.out.println();}public static void listBaseOperator(List ls){ls.add(2,"abc6");sop(ls);//ls.remove(2);//sop(ls);ls.set(2,"abc8");sop(ls);for(int i=0;i<ls.size();i++){System.out.println("ls["+i+"]="+ls.get(i));}printf(ls); ls.add(3,"abc6");ls.add(2,"abc2");printf(ls);int index1 = ls.indexOf("abc2");int index2 = ls.lastIndexOf("abc2");System.out.println("index1="+index1+","+"index2="+index2);List subLs = ls.subList(1,3);printf(subLs);}public static void listIteratorOperator(List ls){/*Iterator it = al.iterator();while(it.hasNext()){Object obj = it.next();if(obj.equals("java02"))//al.add("java008");//在迭代过程中,准备添加或者删除元素,发生错误;迭代操作时,不能同时进行集合方法的操作。it.remove();//将java02的引用从集合中删除了。sop("obj="+obj);}sop(al);*/ListIterator li = ls.listIterator();sop("hasPrevious():"+li.hasPrevious());//hasPrevious():false//sop("pre::"+li.previous());//Exception in thread "main" java.util.NoSuchElementException while(li.hasNext()){Object obj = li.next();if(obj.equals("abc2"))//li.add("java009");li.set("abc6");}while(li.hasPrevious()){sop("pre::"+li.previous());} /*结果:pre::abc6pre::abc1pre::abc0*/sop("hasNext():"+li.hasNext());//hasNext():false,取到了最后,指针后面没有元素了。sop("hasPrevious():"+li.hasPrevious());//hasPrevious():truesop(ls);}public static void main(String[] args) {String[] strArr = {"abc0","abc1","abc2"};List ls = new ArrayList();for(int i=0;i<strArr.length;i++){ls.add(strArr[i]);}sop(ls);//listBaseOperator(ls); listIteratorOperator(ls);}}
import java.util.*;class ArrayListTest1 {public static void sop(Object obj){System.out.println(obj);}public static List removeRepeatElement(List li){List newArr = new ArrayList();//for(int i =0;i<li.size();i++){//Object obj = li.get(i);//if(!newArr.contains(obj)){//newArr.add(obj);//}//}for(Iterator it = li.iterator();it.hasNext();){Object obj = it.next();if(!newArr.contains(obj)){//调用存储对象的equals()方法判断。newArr.add(obj);}}return newArr;}public static void main(String[] args) {List li = new ArrayList();li.add("abc0");li.add("abc1");li.add("abc2");li.add("abc3");li.add("abc1"); sop(li);sop(removeRepeatElement(li));}}
3、LinkedList类*
特有方法:
a、增加:
public void addFirst(E e);
public void addLast(E e);
在JDK1.6出现了替代方法:
public boolean offerFirst(E e);//与addFirst方法没有区别
public boolean offerLast(E e);//与addLast方法没有区别
b、获取
public E getFirst();
public E getLast();
注:获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException
在JDK1.6出现了替代方法:
public E peekFirst();
public E peekLast();
注:获取元素,但不删除元素。如果集合中没有元素,会返回null。
c、获取删除
public E removeFirst();
public E removeLast();
注:获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException
在JDK1.6出现了替代方法:
public E pollFirst();
public E pollLast();
注:获取元素,但是元素被删除。如果集合中没有元素,会返回null。
注:这里不能定义成List的引用,因为这些方法在List接口中都没有,是LinkedList类的特有方法。
import java.util.*;class LinkedListDemo {public static void sop(Object obj){System.out.println(obj);}public static void printf(Collection c){for(Iterator it = c.iterator();it.hasNext();){System.out.print(it.next()+" ");}System.out.println();}public static void main(String[] args) {LinkedList link = new LinkedList();//这里不能定义成List的引用,因为这些方法在List接口中都没有,是LinkedList类的特有方法link.offerFirst("abc0");link.offerFirst("abc1");link.offerFirst("abc2");link.offerFirst("abc3");sop(link);//sop(link.peekFirst());//sop(link);//sop(link.peekFirst());//sop(link);//sop(link.pollFirst());//sop(link);//sop(link.pollFirst());//sop(link);//sop(link.peekLast());//sop(link);//sop(link.pollLast());//sop(link);printf(link);while(!link.isEmpty()){sop(link.pollLast());} printf(link);}}
/*需求:使用LinkedList模拟一个堆栈或者队列数据结构。分析: 堆栈:先进后出 队列:先进先出*/import java.util.*;class MyStack{private LinkedList link;MyStack(){link = new LinkedList();}public void setData(Object o){link.offerFirst(o);}public Object getData(){return link.pollFirst();}public boolean isNotData(){return link.isEmpty();}}class MyQueue{private LinkedList link;MyQueue(){link = new LinkedList();}public void setData(Object o){link.offerFirst(o);}public Object getData(){return link.pollLast();}public boolean isNotData(){return link.isEmpty();}}class LinkedListTest{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {MyQueue mq = new MyQueue();mq.setData("abc01");mq.setData("abc02");mq.setData("abc03");sop(mq.getData());MyStack ms = new MyStack();ms.setData("def01");ms.setData("def02");ms.setData("def03");sop(ms.getData());}}
4、List集合中用contians()判断元素是否相同,依据是元素的equals方法。
remove方法底层也是依赖于元素的equals方法。
/*将自定义对象作为元素存到ArrayList集合中,并去除重复元素。比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。思路:1,对人描述,将数据封装进人对象。2,定义容器,将人存入。3,取出。结论:List集合判断元素是否相同,依据是元素的equals方法; remove方法底层也是依赖于元素的equals方法。*/import java.util.*;class Person{private String name;private int age;Person(String name,int age){this.name = name;this.age = 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));}public void setName(String name){this.name = name;}public String getName(){return name;}public void setAge(int age){this.age = age;}public int getAge(){return age;}}class ArrayListTest2 {public static void sop(Object obj){System.out.println(obj);}public static ArrayList singleElement(ArrayList al){ArrayList newArr = new ArrayList();Iterator it = al.iterator();while(it.hasNext()){Object obj = it.next();if(!newArr.contains(obj))newArr.add(obj);}return newArr;}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("lisi02",32));al.add(new Person("lisi04",35));al.add(new Person("lisi03",33));//al.add(new Person("lisi04",35));//al = singleElement(al);sop("remove 03 :"+al.remove(new Person("lisi03",33)));。Iterator it = al.iterator();while(it.hasNext()){Person p = (Person)it.next();sop(p.getName()+"::"+p.getAge());}}}
五、Set集接口及其相关类
1、Set的共性方法
Set接口中的方法和Collection基本一致。
2、HashSet类*
HashSet保证元素唯一性:通过元素的两个方法,hashCode()和equals()方法来完成。
如果元素的hashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意:(1)对于自定义类的存放到HashSet中元素,需要覆盖hashCode和equals方法。
(2)对于判断元素是否存在,以及删除等操作,依赖的方法是先通过hashCode()比较元素的hashcode值是否相同,
如果相同,再继续判断元素的equals方法,是否为true。
import java.util.*;class Person{private String name;private int age;Person(String name,int age){this.name = name;this.age = age;}public int hashCode(){System.out.println(this.name+"....hashCode");return name.hashCode()+age*37;//37是处理name和age不同,但是相加值相同的情况}public boolean equals(Object obj){if(!(obj instanceof Person))return false;Person p = (Person)obj;System.out.println(this.name+"...equals.."+p.name);return this.name.equals(p.name) && this.age == p.age;}public void setName(String name){this.name = name;}public String getName(){return name;}public void setAge(int age){this.age = age;}public int getAge(){return age;}}class HashSetTest {public static void sop(Object obj){System.out.println(obj);}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));//sop("a1:"+hs.contains(new Person("a2",12)));hs.remove(new Person("a2",12));for(Iterator it = hs.iterator();it.hasNext();){Person p = (Person)it.next();sop(p.getName()+"::"+p.getAge());}}}
3、TreeSet类
a、在TreeSet集合中存储的对象对应的类必须继承Comparable接口,告诉它排序的方法;否则没有办法存储,编译不能通过。
b、TreeSet判断元素唯一性的依据:
在集合初始化时,就有了比较方式。就是根据比较compareTo方法的返回结果是否是0,是0,就是相同元素,不存储。
c、TreeSet集合的底层是二叉树进行排序的
TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法(当主要条件相同时,需要比较次要条件)。
也种方式也成为元素的自然顺序,或者叫做默认顺序。
import java.util.*;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){//return 0; 在集合初始化时,就有了比较方式。就是根据比较compareTo方法的返回结果是否是0,是0,就是相同元素,不存储。if(!(obj instanceof Student))throw new RuntimeException("不是学生对象");Student s = (Student)obj;//System.out.println(this.name+"....compareto....."+s.name);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;}}class TreeSetDemo {public static void main(String[] args){TreeSet ts = new TreeSet();ts.add(new Student("lisi02",22));ts.add(new Student("lisi007",20));ts.add(new Student("lisi09",19));ts.add(new Student("lisi08",19));//ts.add(new Student("lisi007",20));for(Iterator it = ts.iterator();it.hasNext();){Student stu = (Student)it.next();System.out.println(stu.getName()+"..."+stu.getAge());}}}
TreeSet的第二种排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。定义一个类,实现Comparator接口,覆盖compare方法。
如果自定义类实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器
的比较规则为准。
import java.util.*;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;//System.out.println(this.name+"....compareto....."+s.name);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;}}class TreeSetDemo2 {public static void main(String[] args){TreeSet ts = new TreeSet(new MyComparator());ts.add(new Student("lisi02",22));ts.add(new Student("lisi007",20));ts.add(new Student("lisi09",19));ts.add(new Student("lisi08",19));ts.add(new Student("lisi007",23));for(Iterator it = ts.iterator();it.hasNext();){Student stu = (Student)it.next();System.out.println(stu.getName()+"..."+stu.getAge());}}}class MyComparator implements Comparator{public int compare(Object o1,Object o2){Student s1 = (Student)o1;Student s2 = (Student)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;}}
注:不管是在覆盖compareTo方法时,还是覆盖compare方法;当主要条件相同时,需要比较次要条件。
/*需求:按照字符串长度排序。*/import java.util.*;class TreeSetTest {public static void main(String[] args){TreeSet ts = new TreeSet(new MyComparator());ts.add("abcde");ts.add("cd");ts.add("bc");ts.add("dte");ts.add("iop");for(Iterator it = ts.iterator();it.hasNext();){System.out.println(it.next());}}}class MyComparator implements Comparator{public int compare(Object o1,Object o2){String s1 = (String)o1;String s2 = (String)o2; int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));if(num ==0){//排序时,当主要条件相同时,一定判断一下次要条件。return s1.compareTo(s2);}return num;}}
七、Map映射接口及其相关类
1、Map<K,V>集合:
(1) 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
例如:地图上,经纬度和图片地点之间就是典型的Map关系。
(2)Map的键是一个HashSet的集合。
注:Map和Set很像,其实Set底层就是使用了Map集合。
2、Map的共性方法
a、添加:如果添加元素时,出现相同的键。那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。
V put(K key,V value);
void putAll(Map<? extends K,? extends V> m);
b、删除
void clear();
V remove(Object key);
c、判断
boolean containsKey(Object key);
boolean containsValue(Object value);
boolean isEmpty();
d、获取
int size();
V get(Object key);//可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。
Collection<V> values(); //获取map集合中所有的值。
Set<K> keySet();
Set<Map.Entry<K,V>> entrySet();
import java.util.*;class MapDemo{public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>(); System.out.println(map.put("100","abc00"));map.put("101","abc0");map.put("102","abc1");map.put("103","abc2");map.put("104","abc3");map.put("105","abc4");System.out.println(map.put("105","abc5")); System.out.println("map.containKey:"+map.containsKey("102")); //System.out.println("map.remove:"+map.remove("102"));map.put(null,"abc6");System.out.println("get(null):"+map.get(null));map.put("106",null);System.out.println("get:"+map.get("106"));Collection<String> cl = map.values();System.out.println(cl);System.out.println(map);}}
3、map集合的两种取出方式:
(1)Set<k> keySet():将map中所有的键存入到Set集合。因为set具备迭代器。
所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。
(2)Set<Map.Entry<k,v>> entrySet()方法:
a、将map集合中的映射关系存入到了set集合中,即Map.Entry对象。
b、而这个关系的数据类型就是:Map.Entry。Entry其实就是Map中的一个static内部接口。
定义在内部因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。
而且该事物在直接访问Map集合中的元素。
c、Map.Entry内部类有方法
K getKey();
V getValue();
其实Entry也是一个接口,它是Map接口中的一个内部接口(封闭接口)
interface Map{
public static interface Entry{
public abstract Object getKey();
public abstract Object getValue();
}
}
class HashMap implements Map{
class Hahs implements Map.Entry{
public Object getKey(){}
public Object getValue(){}
}
}
注:可以看做在HashMap和TreeMap类内部实现了Entry类,把Key和Value合并成一个特殊形式的字符串,加以保存。
import java.util.*;class MapDemo2{public static void readMethodByKey(Map map){Set<String> set = map.keySet();for(Iterator<String> it = set.iterator();it.hasNext();){String key = it.next();String values = (String)map.get(key);System.out.println("key= "+key+"->"+"values= "+values);}}public static void readMethodByEntry(Map map){Set<Map.Entry<String,String>> entry = map.entrySet();//for(Iterator it = entry.iterator();it.hasNext();){//Map.Entry<String,String> mapEntry = (Map.Entry<String,String>)it.next();for(Iterator<Map.Entry<String,String>> it = entry.iterator();it.hasNext();){Map.Entry<String,String> mapEntry = it.next(); String key = mapEntry.getKey();String values = mapEntry.getValue();System.out.println("key= "+key+"->"+"values= "+values);}}public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>(); map.put("101","abc0");map.put("102","abc1");map.put("103","abc2");map.put("104","abc3");map.put("105","abc4");readMethodByKey(map); //readMethodByEntry(map);System.out.println(map);}}
4、HashMap类*
/*需求:每一个学生都有对应的归属地。 学生Student,地址String。 学生属性:姓名,年龄。 注意:姓名和年龄相同的视为同一个学生,保证学生的唯一性。分析:1、描述学生。2、定义map容器。将学生作为键,地址作为值。存入。3、获取map集合中的元素。*/import java.util.*;class Student implements Comparable<Student>{//使类具有自然的比较顺序,为了存入TreeSet;以及广泛使用。private String name;private int age;Student(String name,int age){this.name = name;this.age = age;}public int compareTo(Student stu){//指定了类型 int num = new Integer(this.age).compareTo(new Integer(stu.age));if(num ==0)return this.name.compareTo(stu.name);return num;}public int hashCode(){return name.hashCode()+age*37;//37是处理name和age不同,但是相加值相同的情况}public boolean equals(Object obj){if(!(obj instanceof Student))//return false; throw new ClassCastException("Type mismatch!");Student p = (Student)obj;return this.name.equals(p.name) && this.age == p.age;}public void setName(String name){this.name = name;}public String getName(){return name;}public void setAge(int age){this.age = age;}public int getAge(){return age;}public String toString(){return (this.name+":"+this.age);}}class MapTest{public static void readMethodByKey(Map map){Set<Student> set = map.keySet();for(Iterator<Student> it = set.iterator();it.hasNext();){Student key = it.next();String values = (String)map.get(key);System.out.println("key= "+key+"->"+"values= "+values);}}public static void readMethodByEntry(Map map){Set<Map.Entry<Student,String>> entry = map.entrySet();for(Iterator<Map.Entry<Student,String>> it = entry.iterator();it.hasNext();){Map.Entry<Student,String> mapEntry = it.next(); Student key = mapEntry.getKey();String values = mapEntry.getValue();System.out.println("key= "+key+"->"+"values= "+values);}}public static void main(String[] args) {Map<Student,String> map = new HashMap<Student,String>(); map.put(new Student("java01",20),"abc0");map.put(new Student("java02",22),"abc1");map.put(new Student("java03",25),"abc2");map.put(new Student("java04",30),"abc3");map.put(new Student("java05",21),"abc4");readMethodByKey(map); //readMethodByEntry(map);System.out.println(map);}}
5、TreeMap类
(1)public TreeMap(Comparator<? super K> comparator);
import java.util.*;class nameComparator implements Comparator<Student>{public int compare(Student s1,Student s2){int value = s1.getName().compareTo(s2.getName());if(value ==0){return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));}return value;}}class MapTest2 {public static void main(String[] args) {Map<Student,String> map = new TreeMap(new nameComparator());map.put(new Student("java01",20),"abc0");map.put(new Student("java02",22),"abc1");map.put(new Student("java03",25),"abc2");map.put(new Student("java04",30),"abc3");map.put(new Student("java04",30),"abc5");map.put(new Student("java05",21),"abc4");Set<Map.Entry<Student,String>> entryset = map.entrySet();for(Iterator<Map.Entry<Student,String>> it = entryset.iterator();it.hasNext();){Map.Entry<Student,String> me = it.next();Student stu = me.getKey();String addr = me.getValue();System.out.println(stu+"::"+addr);}}}
(2)当数据之间存在这映射关系时,就要先想map集合。
/*练习:"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2).....思路1: 1、字母->次数 :Map映射关系; 字母为键值,次数为值 2、处理字符串,存入到Map中,计算次数; a、把字符串处理成char[];b、for-for循环处理;c、记录每个字母次数;d、把字母和次数存入Map集合。 3、打印Map映射。思路2: 1、将字符串转换成字符数组。因为要对每一个字母进行操作。 2、定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。 3、遍历字符数组。 将每一个字母作为键去查map集合。 如果返回null,将该字母和1存入到map集合中。 如果返回不是null,说明该字母在map集合已经存在并有对应次数。 那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。 4、将map集合中的数据变成指定的字符串形式返回。*/import java.util.*;class MapTest3 {public static String charCount(String str){Map<Character,Integer> map = new TreeMap<Character,Integer>(); /*char[] arr = str.toCharArray(); for(int i =0;i<arr.length;i++){int count =0;char s = arr[i];for(int j=0;j<arr.length;j++){ if(arr[i]==arr[j]) count++;}map.put(new Character(arr[i]),new Integer(count));}*///char[] arr = str.toCharArray(); //for(int i =0;i<arr.length;i++){//Integer value = map.get(arr[i]);//if(value == null){//map.put(arr[i],1);//}//else{//map.put(arr[i],(value+1));//}//}char[] arr = str.toCharArray();int count =0; for(int i =0;i<arr.length;i++){if((arr[i]>='a'&&arr[i]<='z')||(arr[i]>='A'&&arr[i]<='Z')){count =0;Integer value = map.get(arr[i]);if(value != null)count = value;count++;map.put(arr[i],count);}} StringBuilder sb = new StringBuilder();Set<Map.Entry<Character,Integer>> entryset = map.entrySet();for(Iterator<Map.Entry<Character,Integer>> it = entryset.iterator();it.hasNext();){Map.Entry<Character,Integer> me = it.next();Character charc = me.getKey();Integer num = me.getValue();sb.append(charc+"("+num+")");}return sb.toString();}public static void main(String[] args){String str = "sdf-gzxcvasdfx-cvdf";String s = charCount(str);System.out.println(s);}}
6、Map扩展:把集合作为元素存储到Map中
/*需求:用Map描述一个公司的结构。销售部:工号 姓名开发部:工号 姓名*/import java.util.*;class Employee{private String workNumber;private String name;Employee(String workNumber,String name){this.workNumber = workNumber;this.name = name;}public String toString(){return (workNumber+"::"+name);}}class MapDemo3{public static void methodOne(){HashMap<String,List<Employee>> company = new HashMap<String,List<Employee>>(); List<Employee> develop = new ArrayList<Employee>();List<Employee> sale = new ArrayList<Employee>();company.put("sale",sale);company.put("develop",develop);sale.add(new Employee("101","abc0"));sale.add(new Employee("102","abc1"));develop.add(new Employee("103","abc2"));develop.add(new Employee("104","abc3"));Iterator<String> it = company.keySet().iterator();while(it.hasNext()){String department = it.next();List<Employee> departmentName = company.get(department); System.out.println(department);Iterator<Employee> its = departmentName.iterator();while(its.hasNext()){Employee employee = its.next();System.out.println(employee);}}} public static void methodTwo(){HashMap<String,HashMap<String,String>> company = new HashMap<String,HashMap<String,String>> (); HashMap<String,String> develop = new HashMap<String,String>();HashMap<String,String> sale = new HashMap<String,String>();company.put("sale",sale);company.put("develop",develop);sale.put("101","abc0");sale.put("102","abc1");develop.put("103","abc2");develop.put("104","abc3");Iterator<String> it = company.keySet().iterator();while(it.hasNext()){String department = it.next();HashMap<String,String> departmentName = company.get(department); System.out.println(department);Iterator<String> its = departmentName.keySet().iterator();while(its.hasNext()){String workNumber = its.next();String name = departmentName.get(workNumber);System.out.println(workNumber+"::"+name);}}}public static void main(String[] args) {methodOne();//methodTwo();}}
八、比较
1、比较器:Comparator接口
(1)对象数组:对应自定义类的比较器需要继承Comparator接口,和覆盖 int compare(T o1,T o2)方法;
(2)对象集合:对应自定义类的比较器需要继承Comparator接口,和覆盖 int compare(T o1,T o2)方法;
并通过集合的构造函数把比较器传入。
2、自然比较方式:Comparable接口
自定义类需要需要继承Comparable接口,和覆盖 int compareTo(T o)方法;
/*需求:按照字符串长度排序。*/import java.util.*;class TreeSetTest {public static void main(String[] args){TreeSet ts = new TreeSet(new MyComparator());ts.add("abcde");ts.add("cd");ts.add("bc");ts.add("dte");ts.add("iop");for(Iterator it = ts.iterator();it.hasNext();){System.out.println(it.next());}}}class MyComparator implements Comparator{public int compare(Object o1,Object o2){String s1 = (String)o1;String s2 = (String)o2; int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));if(num ==0){//排序时,当主要条件相同时,一定判断一下次要条件。return s1.compareTo(s2);}return num;}}
九、包装器
1、Collections
(1)Collections:集合框架的工具类。里面定义的都是静态方法。
(2)Collections和Collection区别:
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。它有两个常用的子接口,
List:对元素都有定义索引。有序的。可以重复元素。
Set:不可以重复元素。无序。
Collections是集合框架中的一个工具类。该类中的方法都是静态的。
提供的方法中有可以对list集合进行排序,二分查找等方法。
通常常用的集合都是线程不安全的。因为要提高效率。
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
(3)常用算法
a、排序
public static <T> void sort(List<T> list,Comparator<? super T> c);
public static <T extends Comparable<? super T>> void sort(List<T> list);//针对List接口中的对象对应的类。
b、最大值
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);
public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp);
c、查找
public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key);
public static <T> int binarySearch(List<? extends T> list, T key,Comparator<? super T> c);
import java.util.*;class StrLenComparator implements Comparator<String>{public int compare(String s1,String s2){int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));if(num ==0)return s1.compareTo(s2);return num;}}class CollectionsDemo{public static void main(String[] args) {//sortDemo();//maxDemo();binarySearchDemo();}public static void binarySearchDemo(){List<String> list = new ArrayList<String>();list.add("abcd");list.add("aaa");list.add("zz");list.add("kkkkk");list.add("qq");list.add("z");//Collections.sort(list);Collections.sort(list,new StrLenComparator());sop(list);//int index = Collections.binarySearch(list,"aaaa");//int index = halfSearch(list,"cc");int index = halfSearch2(list,"aaa",new StrLenComparator());sop("index="+index);} //binarySearch()方法内部的实现public static int halfSearch(List<String> list,String key){int max,min,mid;max = list.size()-1;min = 0;while(min<=max){mid = (max+min)>>1;// /2;String str = list.get(mid);int num = str.compareTo(key);if(num>0)max = mid -1;else if(num<0)min = mid + 1;elsereturn mid;}return -min-1;//}public static int halfSearch2(List<String> list,String key,Comparator<String> cmp){int max,min,mid;max = list.size()-1;min = 0;while(min<=max){mid = (max+min)>>1;// /2;String str = list.get(mid);int num = cmp.compare(str,key);//自定义的比较器的比较方法if(num>0)max = mid -1;else if(num<0)min = mid + 1;elsereturn mid;}return -min-1;}//binarySearch()方法内部的实现public static void maxDemo(){List<String> list = new ArrayList<String>();list.add("abcd");list.add("aaa");list.add("zz");list.add("kkkkk");list.add("qq");list.add("z");list.add("bbbbb");Collections.sort(list);sop(list);//String max = Collections.max(list);String max = Collections.max(list,new StrLenComparator());sop("max="+max);}public static void sortDemo(){List<String> list = new ArrayList<String>();list.add("abcd");list.add("aaa");list.add("zz");list.add("kkkkk");list.add("qq");list.add("z");sop(list);Collections.sort(list);//Collections.sort(list,new StrLenComparator());sop(list);}public static void sop(Object obj){System.out.println(obj);}}
d、替换
public static <T> void fill(List<? super T> list,T obj);
public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal);
public static void swap(List<?> list,int i,int j);
e、反转和反转规则
public static void reverse(List<?> list);
public static <T> Comparator<T> reverseOrder();
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp);
import java.util.*;//反向class StrComparator implements Comparator<String>{public int compare(String s1,String s2){/*int num = s1.compareTo(s2);if(num>0)return -1;if( num<0)return 1;return num;*/return s2.compareTo(s1);}}class StrLenComparator implements Comparator<String>{public int compare(String s1,String s2){int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));if(num ==0)return s1.compareTo(s2);return num;}}class CollectionsDemo2{public static void main(String[] args) {//replaceDemo();//reverseDemo();//reverseorderDemo();shuffleDemo();}public static void shuffleDemo(){List<String> list = new ArrayList<String>();list.add("abcd");list.add("aaa");list.add("zz");list.add("kkkkk");list.add("qq");list.add("z");sop(list);Collections.shuffle(list);sop(list);}public static void reverseorderDemo(){//TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator()));ts.add("abcde");ts.add("aaa");ts.add("k");ts.add("cc");for(String s:ts){System.out.println(s);}}public static void reverseDemo(){List<String> list = new ArrayList<String>();list.add("abcd");list.add("aaa");list.add("zz");list.add("kkkkk");list.add("qq");list.add("z");sop(list); Collections.reverse(list);sop(list);}public static void replaceDemo(){List<String> list = new ArrayList<String>();list.add("abcd");list.add("aaa");list.add("zz");list.add("kkkkk");list.add("qq");list.add("z");sop(list);//Collections.fill(list,"pp");//sop(list); //fillPrcessList(list,2,4);//sop(list);Collections.swap(list,1,4);sop(list);}public static void fillPrcessList(List<String> list,int start,int end){List<String> temp = list.subList(start,end+1);Collections.fill(temp,"pp"); for(int i=start,j=0;i<=end;i++,j++){Collections.replaceAll(list,list.get(i),temp.get(j));}}public static void sop(Object obj){System.out.println(obj);}}
f、多线程同步
public static <T> Collection<T> synchronizedCollection(Collection<T> c);
public static <T> List<T> synchronizedList(List<T> list);
public static <T> Set<T> synchronizedSet(Set<T> s);
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);
2、集合变数组:Collection接口中的toArray方法。
(1)指定类型的数组要定义长度:
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组,就会有null值存入多出来的部分。
所以利用size()方法创建一个刚刚好的数组最优。
(2)将集合变数组目的:
为了限定对元素的操作。不需要进行增删了。
import java.util.*;class CollectionsToArray{public static void main(String[] args) {ArrayList<String> al = new ArrayList<String>();al.add("abc1");al.add("abc2");al.add("abc3");//String[] arr = al.toArray(new String[0]);//[abc1, abc2, abc3]//String[] arr = al.toArray(new String[5]);//[abc1, abc2, abc3, null, null]String[] arr = al.toArray(new String[al.size()]);System.out.println(Arrays.toString(arr));}}
3、Arrays类
(1)Arrays:用于操作数组的工具类。里面都是静态方法。
public static <T> void sort(T[] a, Comparator<? super T> c);
public static void sort(Object[] a);//针对数组,任何元素组成的,包括自定义类组成的。
public static <T> int binarySearch(T[] a,T key,Comparator<? super T> c);
(2)将数组变成list集合:asList()
a、把数组变成list集合好处:可以使用集合的思想和方法来操作数组中的元素。
b、将数组变成集合,不可以使用集合的增删方法。因为数组的长度是固定。只能使用:
contains();
get();
indexOf();
subList();
如果你增删。那么会反生UnsupportedOperationException,
c、如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
import java.util.*;class ArraysDemo{public static void main(String[] args) {//int[] arr = {2,4,5};//System.out.println(Arrays.toString(arr));//String[] arr = {"abc","cc","kkkk"};//List<String> list = Arrays.asList(arr);//sop("contains:"+list.contains("cc"));////list.add("qq");//UnsupportedOperationException,//sop(list);int[] nums = {2,4,5};List li = Arrays.asList(nums);//[[I@1db9742] 等价于 List<int[]> li = Arrays.asList(nums);sop(li);Integer[] num = {2,4,5};List<Integer> lis = Arrays.asList(num);sop(lis);}public static boolean myContains(String[] arr,String key){for(int x=0;x<arr.length; x++){if(arr[x].equals(key))return true;}return false;}public static void sop(Object obj){System.out.println(obj);}}
- 黑马程序员-Java的集合类(java中类的容器)和算法
- 黑马程序员——java中容器(集合类)
- 黑马程序员--java基础--java中常用的"容器"-集合
- 黑马程序员----JAVA中各种容器的区别和方法
- 黑马程序员---Java 容器集合
- 常见的集合类容器(java)
- 黑马程序员:java集合类
- 黑马程序员-----java集合类
- 【黑马程序员】Java集合类
- 黑马程序员--javaSE--java集合容器总结
- java的集合框架工具类(黑马程序员)
- 黑马程序员:Java基础总结----集合框架的工具类
- 黑马程序员——java的集合类
- 黑马程序员-----Java中类的初始化
- 黑马程序员—13—java基础:有关集合类的学习笔记和心得体会
- 黑马程序员-Java的集合类(泛型、可变参数、for-each循环和静态导入)
- Java中常见的集合容器类关系图
- 黑马程序员 Java的集合框架
- Android 数据存储(三) 数据库存储
- 【git】VS2015使用Git
- RTTI
- HDU 1015 Safecracker 模拟
- javascript的offset、client、scroll使用方法详解
- 黑马程序员-Java的集合类(java中类的容器)和算法
- Hibernate 中出现 users is not mapped 问题
- 使用ShareSDK 微信分享闪退问题总汇
- asp.net 视图(viewState)的优缺点
- k近邻算法
- 10个迷惑新手的Cocoa&Objective-c开发问题
- 最短路径之Floyd算法
- uva10098(简单题)-全排列
- 共享锁与排它锁