集合框架
来源:互联网 发布:淘宝的软件靠谱么 编辑:程序博客网 时间:2024/06/11 09:53
集合框架
在没有学集合框架之前,我们存多个数据只会用数组,但是学了集合类后,我们存储多个数据就可以直接调用。
在总结集合笔记之前,我们先学泛型,以泛型进入集合会更好理解。
泛型:
一、泛型的含义:
1、广泛通用的类型。
2、代码模板中类型不确定,谁调用该段代码,谁指明类型是什么。
二、为什么要使用泛型?
1、存储任意类型的数据在集合中 ,但是取出来都是Object类型的,此时就得强转,使用泛型避免了数据类型转换的异常。
2、约束存储到集合中的元素必须是相同的数据类型(相同的数据类型才能做比较,比如TreeSet类)。
3、设计一个点(Point)类,来封装坐标位置,要求坐标位置支持引用数据类型(String类型.Integer类型/Double类型)。
三、泛型的使用:
1、保证前后类型相同。
2、泛型与子类继承的限制(在泛型中不能用父类来接受子类)。
3、泛型类中的泛型只能适用于非静态方法。
4、型类中的泛型应该适用于整个类中多个方法,有时候只对某一个方法设置泛型即可。
Demo:
public class GeneralDemo2 { public static void main(String[] args) {System.out.println(MethodDemo.test("huairen"));Person1<String,Car<Integer>> p = new Person1<String,Car<Integer>>("张浩", new Car<Integer>(2));System.out.println(p.getTemp1()+p.getTemp2());} }//静态方法不能使用类上定义的泛型class MethodDemo<V>{public static <T> T test(T temp){return temp;}//错误/*public static void test2(V temp){System.out.println(temp);}*/public <T> T[] test3(T[] temp){return temp;}} class Person1<V,T>{private V temp1;private T temp2;public Person1(V temp1, T temp2) {this.temp1 = temp1;this.temp2 = temp2;}public V getTemp1() {return temp1;}public void setTemp1(V temp1) {this.temp1 = temp1;}public T getTemp2() {return temp2;}public void setTemp2(T temp2) {this.temp2 = temp2;}} class Car<V>{private V temp; public Car(V temp) {this.temp = temp;} public V getTemp() {return temp;} public void setTemp(V temp) {this.temp = temp;} @Overridepublic String toString() {return "此车"+temp+"轮胎";}}
四、通配符:
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知此时只能接受数据,不能往该集合中存储数据。
泛型的上限和下限:用来限定元素的类型必须是X类的子类或相同, X的父类或相同。
Demo:
public class GeneralDemo { public static void main(String[] args) {//1.泛型中不能使用基础数据类型,只能使用包装类//泛型中不能使用父类接收子类Point<Integer,String> p2 = new Point<Integer,String>(2,"北纬22度");System.out.println(p2);new Person().getPoint(p2);}}class Person{//extends相当于小于或等于//super相当于大于等于public void getPoint(Point<?extends Number,?super String> p){System.out.println("人在"+p);}}class Point<T,V>{private T x;private V y;public Point(T x, V y) {this.x = x;this.y = y;}public T getX() {return x;}public void setX(T x) {this.x = x;}public V getY() {return y;}public void setY(V y) {this.y = y;}public String toString() {return "("+x+","+y+")";}}
五、泛型数组:
Demo:
public class GenericsDemo { public static void main(String[] args) {Integer[] a = {1,2,3,4,5};GenericsArrays ga = new GenericsArrays();ga.test(a);Integer[] b = ga.testReturn(a);for (int i = 0; i < b.length; i++) {System.out.println(b[i]);} }} class GenericsArrays{public<T> void test(T a[]) {for (int i = 0; i < a.length; i++) {System.out.println(a[i]);}System.out.println("-------");}public<T> T[]testReturn(T a[]){return a;}}
----------------------------------------------------------------
集合:
一、什么是集合?
集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法(底层都对应着某一种数据结构的算法)。
集合也就是一个动态的对象数组,可以不限制定义,不像数组那样有长度限制。
二、常用的框架接口规范:
1、集合中存储的对象,称之为集合元素;
2、集合中只能存储任意类型的对象;
3、集合中只能存储对象,不能存储基本数据类型的值;
4、集合类中存储的对象,都存储的是对象的引用,而不是对象本身.
三、常用的集合类:
1、Set(集):集合中的对象不按特定方式排序,不允许元素重复.
2、 List(列表):集合中的对象按照索引位置排序,允许元素重复.
3、Map(映射):集合中每一个元素都包含一对key和value对象.不允许key对象重复,值对象可以重复
四、集合类的操作方法:
1、增加:
A) boolean add(Object e) 将指定元素添加到此向量的末尾,等价于addElement方法。
B) void add(int index, Object element) 在此向量的指定位置插入指定的元素。
C) boolean addAll(Collection c) :把c集合中的元素添加到当前集合对象中.
2、删除:
A) Object remove(int index) :删除指定索引位置的元素,并返回删除之后的元素.
B) boolean remove(Object o):删除指定的元素.
boolean removeAll(Collection c):从此集合中移除包含在指定 集合c中的所有元素。
C) boolean retainAll(Collection c):在此集合中仅保留包含在指定 集合c中的元素,求两个集合的交集。
3、修改:
A) Object set(int index, Object element) :修改当前集合中指定索引位置的元素。返回被替换的旧的元素.
4、查询:
A) int size() :返回当前集合中存储几个元素.
B) boolean isEmpty():如果当前集合中不包含指定元素,是则返回true.
C) boolean contains():如果当前集合中包含指定元素,是则返回true.
D) Object get(int index):查询指定索引位置的元素.
E) Object[] toArray():把集合对象转换为Object数组.
五、List类
特点:1)可以重复放入元素,只会删除集合中最先找到的元素;
2)记录元素的先后添加顺序。
ArrayList类:
1、ArrayList类相当于vector类是一个Object数组,是Java集合框架出现之后用来取代Vector类的,二者底层原理都是基于数组的算法,一模一样。
2、区别:
A) Vector: 所有的方法都使用了synchronized修饰符. 线程安全但是性能较低. 适用于多线程环境.
B) ArrayList:所有的方法都没有使用synchronized修饰符. 线程不安全但是性能较高.
即使以后在多线程环境下,我们也不使用Vector类:
ArrayList list = Collections.synchronizedList(new ArrayList(...));
LinkedList子类(一个链表操作类):
1、定义:LinkedList类是双向链表,单向队列,双向队列,栈的实现类:
2、LinkedList类实现单向队列和双向队列的接口,自身提高了栈操作的方法,链表操作的方法.
3、在LinkedList类中存在很多方法,但是功能都是相同的.LinkedList表示了多种数据结构的实现,每一种数据结构的操作名字不同。
4、LinkedList擅长保存和删除操作。
Demo:
public class LinkedListDemo {public static void main(String[] args) {//创建链表LinkedList<String> ld = new LinkedList<String>();ld.add("苹果1");ld.add("苹果2");ld.add("苹果3");ld.add("苹果4");ld.add("苹果5");System.out.println(ld);//在链表首尾添加ld.addFirst("苹果0");ld.addLast("苹果6");System.out.println(ld);//找到链表的头System.out.println(ld.element());System.out.println(ld.peek());System.out.println(ld.poll());System.out.println(ld);//按照先进先出的思想取出链表里的元素for(int i=0;i<6;i++){//注意这里不能写成 ld.size();因为ld.size()的值在随着链表里的元素被移除而变化System.out.println(ld.poll()+":"+i);}}//element:找到头;//peek:找到头;//poll:找到头并删除头;}
七、迭代器(Iterator):
1、迭代器对象:
A) Iterator: 迭代器对象,只能从上往下迭代.
B) boolean hasNext(); 判断当前指针后是否有下一个元素
C) Object next():获取指针的下一个元素,并且移动指针.
D) ListIterator: 是Iterator接口的子接口,支持双向迭代,从上往下迭代,从下往上迭代.
Demo:
public class IteratorDemo { public static void main(String[] args) {List<Apple> a = new ArrayList<Apple>();a.add(new Apple("a1"));a.add(new Apple("a2"));a.add(new Apple("a3"));a.add(new Apple("a4"));a.add(new Apple("a5"));Iterator<Apple> it = a.iterator();while(it.hasNext()) {System.out.println(it.next()+",");}}}class Apple{private String name; public Apple(String name) {super();this.name = name;} @Overridepublic String toString() {return "Apple [name=" + name + "]";}}
八、Set类:
特点:1):不允许元素重复(采用散列存储);
2):不会记录元素的先后添加顺序;
3):Set判断两个对象是否相等用equals,而不是使用==。也就是说两个对象equals比较返回true,Set集合是不会接受这个两个对象的。
Hashset类:
1、不保证元素的先后添加顺序.
2、底层才有的是哈希表算法,查询效率极高.
3、判断两个对象是否相等的规则:
a):equals比较为true.
b):hashCode值相同.
要求:要求存在在哈希中的对象元素都得覆盖equals和hashCode方法.
HashSet做等值查询效率高,TreeSet做范围查询效率高.
Demo:
public class TreeSetDemo1 {public static void main(String[] args) {HashSet<Dog> ts = new HashSet<Dog>();ts.add(new Dog("狗1", 6));ts.add(new Dog("狗2", 4));ts.add(new Dog("狗2", 4));ts.add(new Dog("狗2", 4));ts.add(new Dog("狗3", 2));ts.add(new Dog("狗4", 5));System.out.println(ts);}}class Dog{private String name;private int age;public Dog(String name, int age) {this.name = name;this.age = 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 (this.name + ":" + this.age);}public boolean equals(Object obj){//首先判断是不是我们要判断的类型if(!(obj instanceof Dog)){return false;}//判断是不是不同名字,但是指向了同一个if(this == obj ){return true;}//判断是不同的对象,但是值确是一样Dog d = (Dog)obj;if(this.age == d.getAge()&&this.getName()==d.getName()){return true;}else{return false;}}public int hashCode(){return this.name.hashCode();//return this.name.hashCode()*this.age;}}
TreeSet类:
1、不保证元素的先后添加顺序,但是会对集合中的元素做排序操作.
2、底层才有红黑树算法(树结构,比较擅长做范围查询).
TreeSet要么才有自然排序,要么定制排序.
A) 自然排序: 要求在TreeSet集合中的对象必须实现java.lang.Comparable接口,并覆盖compareTo方法.
B) 定制排序: 要求在构建TreeSet对象的时候,传入一个比较器对象(必须实现java.lang.Comparator接口).在比较器中覆盖compare方法,并编写比较规则.
3、TreeSet判断元素对象重复的规则:
compareTo/compare方法是否返回0.如果返回0,则视为是同一个对象.
Demo:
public class TreeSetDemo { public static void main(String[] args) {/*TreeSet<Animal> ts = new TreeSet<>();ts.add(new Animal("dog1",2));ts.add(new Animal("cat2",1));ts.add(new Animal("bird3",4));ts.add(new Animal("dog4",2));System.out.println(ts);*///[Animal [name=cat2, age=1], Animal [name=dog1, age=2], Animal [name=bird3, age=4]] Animal[] a = {new Animal("dog1",2), new Animal("cat2",1), new Animal("cat3",1), new Animal("dog4",3)};Arrays.sort(a);for (int i = 0; i < a.length; i++) {System.out.println(a[i]);}//Animal [name=cat2, age=1]Animal [name=cat3, age=1]Animal [name=dog1, age=2]Animal [name=dog4, age=3]} }class Animal implements Comparable<Animal>{private String name;private Integer age;Animal(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public int compareTo(Animal a) {if (this.age > a.getAge()) {return 1;}else if(this.age < a.getAge()) {return -1;}else {return 0;}}@Overridepublic String toString() {return "Animal [name=" + name + ", age=" + age + "]";}}
九、Map类(映射):
1、Map的常用实现类:
A) HashMap: 采用哈希表算法,此时Map中的key不会保证添加的先后顺序,key也不允许重复. key判断重复的标准是: key1和key2是否equals为true,并且hashCode相等.
B) TreeMap:采用红黑树算法,此时Map中的key会按照自然顺序或定制排序进行排序,,key也不允许重复. key判断重复的标准是: compareTo/compare的返回值是否为0.
C) LinkedHashMap: 采用链表和哈希表算法,此时Map中的key会保证先后添加的顺序,key不允许重复. key判断重复的标准和HashMap中的key的标准相同.
【注】HashMap和TreeMap以及LinkedHashMap都是线程不安全的,但是性能较高:
解决方案: Map m = Collections.synchronizedMap(Map对象);
Hashtable类实现线程安全的,但是性能较低.
哈希表算法:做等值查询最快.
数结构算法:做范围查询最快-->应用到索引上.
2、一般的,我们定义Map,key都使用不可变的类(String),把key作为value的唯一名称.
Demo:
public class MapDemo { public static void main(String[] args) {//利用Iterator输出Map(Map一般都是供查询,很少直接输出,但是一旦要输出必须按一下标准格式)/*Map<String, Object> map = new HashMap<String,Object>();map.put("lisi", "川大");map.put("zhangsan", "电子科大");map.put("wangwei", "北大");Set<Map.Entry<String, Object>> entrys = map.entrySet();for (Map.Entry<String, Object> entry : entrys) {String key = entry.getKey();Object values = entry.getValue();System.out.println(key+"<--->"+values);}*/ //需求:计算一个字符串中每个字符出现的次数:String str = "helowjfjsvnfdjfdfdddhsefew";//字符串本质是char[]char[] arr = str.toCharArray();Map<Character, Integer> map = new TreeMap<>();for (char ch:arr) {//判断当前字符是否在Map中的key存在if (map.containsKey(ch)) {//当前Map的key包含该字符,取出value值递增1,再存放进去Integer old = map.get(ch);map.put(ch, old+1);} else {//当前Map的key不包含该字符,取出value值为1map.put(ch, 1);}}System.out.println(map);} }
十、List、Set和Map的选用:
1、选用哪一种容器取决于每一种容器的存储特点以及当前业务的需求:
A) List: 单一元素集合.
允许元素重复/记录元素的添加顺序.
B) Set:单一元素集合.
不允许元素重复/不记录元素的添加顺序.
既要不重复,又要保证先后顺序:LinkedHashSet.
C) Map: 双元素集合.如果存储数据的时候,还得给数据其为一个的一个名称,此时考虑使用Map.
2、List和Set以及Map之间相互转换问题:
List<String> list = new ArrayList<>();
把List转换为Set:
Set<String> set = new HashSet<>(list);//此时会消除重复的元素.
把Set转换为List:
List<String> list2 = new ArrayList<>(set );
Map不能直接转换为List或Set(但是Map中的方法可以间接转换).
十一、集合工具类(Collections)
1、为集合添加内容
List<String> all= new ArrayList<String>();
Collections.addAll(all,"haoren","huairen","person";
2、反转
collections.reverse(all);
3、替换
collections.replaceAll(all,"haoren","mz");
4、排序
collections.sort(all);
5、查找
collections.binarySearch(all,“haoren”);(先要排序,因为使用二分法)
6、交换指定位置的内容
collections.swap(all,1,2);
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- 集合框架
- QT资料搜集页
- 声学特征 PNCC
- output标签实现滑块输出值跟踪
- 编译caffe出错
- 《MySQL入门》
- 集合框架
- 解决u-boot 2016.11 ”ERROR: Makefile:1385: recipe for target 'checkarmreloc' failed”
- 如何用C++实现自己的Tensorflow
- javascript中call apply bind详解
- sigmoid和softmax总结
- SSH项目整合碰到异常及解决方法
- 简单三色塔(c/python略)
- ### net.sf.json.JSONException: There is a cycle in the hierarchy!
- Tensoflow+CNN实现简单的mnist手写数字识别