集合框架

集合框架

在没有学集合框架之前,我们存多个数据只会用数组,但是学了集合类后,我们存储多个数据就可以直接调用。

在总结集合笔记之前,我们先学泛型,以泛型进入集合会更好理解。

泛型:

一、泛型的含义:

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;
}
 
@Override
public 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、集合类中存储的对象,都存储的是对象的引用,而不是对象本身.


三、常用的集合类:

1Set():集合中的对象不按特定方式排序,不允许元素重复.

 2 List(列表):集合中的对象按照索引位置排序,允许元素重复.

3Map(映射):集合中每一个元素都包含一对keyvalue对象.不允许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类是双向链表,单向队列,双向队列,栈的实现类:

2LinkedList类实现单向队列和双向队列的接口,自身提高了栈操作的方法,链表操作的方法.

3、在LinkedList类中存在很多方法,但是功能都是相同的.LinkedList表示了多种数据结构的实现,每一种数据结构的操作名字不同。

4LinkedList擅长保存和删除操作。

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;
}
 
@Override
public String toString() {
return "Apple [name=" + name + "]";
}
}


八、Set类:

特点:1):不允许元素重复(采用散列存储);

      2):不会记录元素的先后添加顺序;

3)Set判断两个对象是否相等用equals,而不是使用==。也就是说两个对象equals比较返回trueSet集合是不会接受这个两个对象的。

Hashset类:

 1不保证元素的先后添加顺序.

  2、底层才有的是哈希表算法,查询效率极高.

  3判断两个对象是否相等的规则:                                               

 a):equals比较为true.

 b):hashCode值相同.

要求:要求存在在哈希中的对象元素都得覆盖equalshashCode方法.    

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方法,并编写比较规则.

3TreeSet判断元素对象重复的规则:                                        

 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;
}
}
@Override
public String toString() {
return "Animal [name=" + name + ", age=" + age + "]";
}
}


九、Map类(映射):

1Map的常用实现类:

A) HashMap: 采用哈希表算法, 此时Map中的key不会保证添加的先后顺序,key也不允许重复.  key判断重复的标准是: key1key2是否equalstrue,并且hashCode相等.

B) TreeMap: 采用红黑树算法,此时Map中的key会按照自然顺序或定制排序进行排序,,key也不允许重复.  key判断重复的标准是: compareTo/compare的返回值是否为0.

C) LinkedHashMap: 采用链表和哈希表算法,此时Map中的key会保证先后添加的顺序,key不允许重复.  key判断重复的标准和HashMap中的key的标准相同.

HashMapTreeMap以及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值为1
map.put(ch, 1);
}
}
System.out.println(map);
}
 
}


十、ListSetMap的选用:

1选用哪一种容器取决于每一种容器的存储特点以及当前业务的需求:

A) List:  单一元素集合.

         允许元素重复/记录元素的添加顺序.

B) Set:单一元素集合.

        不允许元素重复/不记录元素的添加顺序.

既要不重复,又要保证先后顺序:LinkedHashSet. 

C) Map: 双元素集合. 如果存储数据的时候,还得给数据其为一个的一个名称,此时考虑使用Map.

2ListSet以及Map之间相互转换问题:

  List<String> list = new ArrayList<>();

  List转换为Set:

  Set<String> set = new HashSet<>(list);//此时会消除重复的元素.

  Set转换为List:

  List<String> list2 = new ArrayList<>(set );

  Map不能直接转换为ListSet(但是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);

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值