Java基础知识(数据类型和集合)

一、数据类型

包装类型

包装类型是对基本数据类型不足之处的补充。

基本数据类型的传递方式是值传递,而包装类型是引用传递,同时提供了很多数据类型间转换的方法。

Java1.5 以后可以自动装箱和拆箱

二、集合

List:有序、可重复。可以通过索引快速查找,但进行增删操作时后续的数据需要移动,所以增删速度慢。 List 接口的大小可变数组的实现,即:可以直接指定容量大小

|--ArrayList:底层数据结构是 数组结构.是线程不同步的(不安全的).查询速度很快,但是增删较慢。

             构造一个初始容量为 10 的空列表,当放满了10个元素后,以50%的长度加长集合容器的长度。

|--LinkedList:底层数据结构是 链表结构。对元素的增删速度很快。但是查询速度很慢。线程是不同步的。

|--Vector:底层数据结构也是数组结构,是线程同步的(安全的),效率低,被ArrayList替代了。1.2版本以后的集合都是不同步的;当放满了10个元素后,以100%的长度加长集合容器的长度。

Vector的特有功能

1、添加功能

public void addElement(Object obj)

2、获取功能

public Object elementAt(int index)

public Enumeration elements()

LinkedList的特有功能

1、添加功能

public void addFirst(Object e)

public void addLast(Object e)

2、获取功能

public Object getFirst()

public Object getLast()

3、删除功能

public Object removeFirst()

public Object removeLast()

ArrayList和LinkedList的区别

ArrayList扩容是将就得数组复制到新的数组的过程,所以会时间损耗是复制移动的时间,空间损耗是新的数组是按1.5倍扩容,复制移动完数据可能会有剩余空间浪费

1.ArrayList是实现了基于动态数组的数据结构,每个元素在内存中存储地址是连续的;LinkedList基于链表的数据结构,每个元素内容包扩previous, next, element(其中,previous是该节点的上一个节点,next是该节点的下一个节点,element是该节点所包含的值),也是由于这一性质支持了每个元素在内存中分布存储。

2.为了使得突破动态长度数组而衍生的ArrayList初始容量为10,每次扩容会固定为之前的1.5倍,所以当你ArrayList达到一定量之后会是一种很大的浪费,并且每次扩容的过程是内部复制数组到新数组;LinkedList的每一个元素都需要消耗一定的空间

3.对于每个元素的检索,ArrayList要优于LinkedList。LinkedList不 支持高效的随机元素访问;因为ArrayList从一定意义上来说,就是复杂的数组,所以基于数组index的  检索性能显然高于通过for循环来查找每个元素的LinkedList。

4.元素插入删除的效率对比,要视插入删除的位置来分析,各有优劣

在列表首位添加(删除)元素,LnkedList性能远远优于ArrayList,原因在于ArrayList要后移(前移)每个元素的索引和数组扩容(删除元素时则不需要扩容)。(测试的时候当然插入一次是看不出来什么的,我自己测试插入十万次,就会有数组扩容arraycopy的因素)而LinkedList则直接增加元素,修改原第一元素该节点的上一个节点即可,删除同理

在列表中间位置添加(删除)元素,总的来说位置靠前则LnkedList性能优于ArrayList,靠后则相反。出现这种情况的原因在于ArrayList性能主要损耗在后移(前移)该位置之后的元素索引,而LinkedList损耗在for循环从第一位检索该位置的元素。这个性能反转的临界点不固定,我自己测试插入十万次,在15000次左右损耗时间相比出现变化

在列表末尾位置添加(删除)元素,性能相差不大。

Set:无序、不可重复。

Collection
|--List
有序(存储顺序和取出顺序一致),可重复
|--Set
无序(存储顺序和取出顺序不一致),唯一

HashSet:它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
注意:虽然Set集合的元素无序,但是,作为集合来说,它肯定有它自己的存储顺序,
而你的顺序恰好和它的存储顺序一致,这代表不了有序,你可以多存储一些数据,就能看到效果。

HashSet的唯一性

问题:为什么存储字符串的时候,字符串内容相同的只存储了一个呢?

通过查看add方法的源码,我们知道这个方法底层依赖 两个方法:hashCode()和equals()。
步骤:
首先比较哈希值
如果相同,继续走,比较地址值或者走equals()
如果不同,就直接添加到集合中
按照方法的步骤来说:
先看hashCode()值是否相同
相同:继续走equals()方法
返回true: 说明元素重复,就不添加
返回false:说明元素不重复,就添加到集合
不同:就直接把元素添加到集合
如果类没有重写这两个方法,默认使用的Object()。一般来说不同相同。
而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个

哈希表:是一个元素为链表的数组,

LinkedHashSet:底层数据结构由哈希表和链表组成。 哈希表保证元素的唯一性。 链表保证元素有素。(存储和取出是一致)

TreeSet:能够对元素按照某种规则进行排序。 排序有两种方式 A:自然排序 B:比较器排序 TreeSet集合的特点:排序和唯一 通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法。

A:自然排序(元素具备比较性) 让元素所属的类实现自然排序接口 Comparable B:比较器排序(集合具备比较性) 让集合的构造方法接收一个比较器接口的子类对象 Comparator

自然排序

package cn.itcast_05;

import java.util.TreeSet;

public class TreeSetDemo2 {
public static void main(String[] args) {
// 创建集合对象
TreeSet<Student> ts = new TreeSet<Student>();

// 创建元素
Student s1 = new Student("linqingxia", 27);
Student s2 = new Student("zhangguorong", 29);
Student s3 = new Student("wanglihong", 23);
Student s4 = new Student("linqingxia", 27);
Student s5 = new Student("liushishi", 22);
Student s6 = new Student("wuqilong", 40);
Student s7 = new Student("fengqingy", 22);

// 添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);

// 遍历
for (Student s : ts) {
System.out.println(s.getName() + "---" + s.getAge());
}
}
}


/*学生类*/
package cn.itcast_05;

/*
* 如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
*/
public class Student implements Comparable<Student> {
private String name;
private int age;

public Student() {
super();
}

public Student(String name, int age) {
super();
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;
}

@Override
public int compareTo(Student s) {
// return 0;
// return 1;
// return -1;

// 这里返回什么,其实应该根据我的排序规则来做
// 按照年龄排序,主要条件
int num = this.age - s.age;
// 次要条件
// 年龄相同的时候,还得去看姓名是否也相同
// 如果年龄和姓名都相同,才是同一个元素
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
}
---------------------
作者:小峰峰疯疯的
来源:CSDN
原文:https://blog.csdn.net/gafeng123456/article/details/50772296
版权声明:本文为博主原创文章,转载请附上博文链接!

比较器排序

package cn.itcast_07;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
public static void main(String[] args) {
// 创建集合对象
// TreeSet<Student> ts = new TreeSet<Student>(); //自然排序
// public TreeSet(Comparator comparator) //比较器排序
// TreeSet<Student> ts = new TreeSet<Student>(new MyComparator());

// 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象
// 而匿名内部类就可以实现这个东西
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 姓名长度
int num = s1.getName().length() - s2.getName().length();
// 姓名内容
int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
: num;
// 年龄
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
}
});

// 创建元素
Student s1 = new Student("linqingxia", 27);
Student s2 = new Student("zhangguorong", 29);
Student s3 = new Student("wanglihong", 23);
Student s4 = new Student("linqingxia", 27);
Student s5 = new Student("liushishi", 22);
Student s6 = new Student("wuqilong", 40);
Student s7 = new Student("fengqingy", 22);
Student s8 = new Student("linqingxia", 29);

// 添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
ts.add(s8);

// 遍历
for (Student s : ts) {
System.out.println(s.getName() + "---" + s.getAge());
}
}
}

Map:键值对、键唯一、值不唯一。Map 集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对 map 集合遍历时先得到键的 set 集合,对 set 集合进行遍历,得到相应的值。
Map集合常用的子类有两种: HashMap  TreeMap

1.HashMap集合

注意:

             Map集合都是针对键有效,且键是唯一的, 如果有相同的键,则第二个键的值覆盖掉第一个键的值,如果第一次给HashMap添加元素,则put()方法返回值为null,第二次添加相同键的元素,则返回第一次添加的元素的值

 存储自定义对象的两种方式:

              自定义对象为键  :不能重复 ,需要重写equals()和HashCode()两个方法

              自定义对象为值  :可以重复

注释:

              如果成员变量的值相同则认为是同一个人,即重复
              HashMap底层依赖的是哈希表
              哈希表依赖于两个方法:equals()和HashCode();

 //自定义对象作为键,必须具有唯一性,输出不能保证顺序

面试题:  

     HashMap和HashTable的区别?

                     共同点:都是基于Map集合的实现类,都是哈希表的实现类
                   HashMap集合:线程不安全,执行效率高,不同步,允许null值和null键
                   HashTable集合:线程安全,执行效率低,同步,不允许null值和null键

线程安全的类:
                   StringBuffer    :字符串缓冲区
                   Vector             :List集合的子集合
                   HashTable       :Map集合的子集合

2.LinkedHashMap集合

     LinkedHashMap集合是Map接口基于哈希表和链表实现的
   
    哈希表可保证键的唯一性

    链表保证了元素的有序性(存储和取出一致)

3.TreeMap集合

TreeMap集合的两种排序方式:

自然排序:自定义的类实现Comparable接口,通过无参构造形式创建对象,并且重写ComparaTo()方法
比较器排序:通过public TreeSet(Comparator<E> comparator)构造方法创建对象,并且重写了Compare()方法
       比较器排序的两种方式:
                     1).创建实现类继承Comparator接口,并且重写Compare()方法

                     2).直接使用匿名内部类实现 ,重写Compare()方法,不用创建实现类

  TreeSet集合保证元素是看ComparaTo()方法或者Compare()方法返回值是否为0;

  TreeSet集合底层依赖于TreeMap集合的方法,存储方式为红黑树结构
4.Collections工具类

 Collections和Collection的区别:
         Collection:顶层次单列集合的根接口,它是一个集合,也是一个接口
         Collections:是针对集合操作的工具类,里面包含了一些功能,随机置换,集合里面的二分
         查找,将集合的元素进行反转
        
 Collections集合的常用方法:
         public static <T> int binarySearch(List<T> list,T key)   二分查找
         public static  T max(Collection coll): 获取集合中的最大值
         public static void reverse(List<?> list) :将集合中的元素顺序反转
         public static void shuffle(List<?> list) :将集合中的元素打乱

         public static void sort(List<> list) :将集合中的元素进行排序

猜你喜欢

转载自www.cnblogs.com/h-c-g/p/10391551.html
今日推荐