Java中的复合数据类型

目录
  • 1、Java字符串
  • 2、Java中的包装类
  • 3、Java容器
    • ArrayList
    • HashSet
    • HashMap
  • 4、工具类
    • Stack
    • Queue

1、Java字符串

在 Java 中字符串被作为 String 类型的对象处理。 String 类位于 java.lang 包中,默认情况下该包自动导入。

String对象创建后不会被修改,当我们修改某个字符串对象实际上是将原引用指向了新创建的内存空间。并且相同的字符串常量Java不会分配两个内存空间,而是将两个引用指向相同的空间。

public class MyString {
    public static void main(String[] args) {
        String s1="字符串";
        String s2="字符串";
        String s3=s1;
        System.out.println(s1==s2);     // s1、s2字符串内容相同,指向相同的内存空间,输出:true
        System.out.println(s1==s3);     // 修改之前s1与s3相同,输出:true
        s1="修改字符串";
        System.out.println(s1==s3);     // 修改之后s1指向新的内存空间,与s3不同,输出:false
    }
}

String中常用的方法:

str.length()    //返回当前字符串的长度
str.indexOf(int ch)    //查找ch字符在该字符串中第一次出现的位置,若无返回-1
str.indexOf(subStr)    //查找str子字符串在该字符串中第一次出现的位罝
str.lastIndexOf(ch)    //查找ch字符在该字符串中最后一次出现的位置
str.lastlndexOf(subStr)查找St子字符串在该字符串中最后一次出现的位置
str.substring(beginlndex)    //获取从beginlndex位置幵始到结朿的子字符串
str.substring(beginlndex, endlndex)    //获取从beginlndex位置幵始到endlndex位M的子字符串
str.trim()        //返回去除了前后空格的字符串
str.equals(obj)        //将该字符串与指定对象比较,返回true或false
str.toLowerCase()        //将字符串转换为小写
str.toUpperCase()        //将字符串转换为大写
str.charAt(int index)    //获取字符串中指定位置的字符
str.setCharAt(i,c)    //设置某个位置的字符串
str.split(String regex, int limit)        //将字符串分割为子字符串,返回字符串数组
str.concat(str2)        //将str2拼接到末尾
str.getBytes()        /将该字符串转换为byte数组
str.toCharArray()        //转化为字符数组

如果需要使用经常修改的字符串,可以用StringBuilder类来保存,可以通过append、replace等方法对字符串进行修改,修改之后仍然指向同一块内存地址

public class MyString {
    public static void main(String[] args) {
        StringBuilder s4=new StringBuilder("初始字符串");
        StringBuilder s5=s4;
        s4.replace(0,10,"修改后的字符串");
        System.out.println(s4);
        System.out.println(s4==s5);     // 修改后仍然指向同一块内存,因此输出:true
    }
}

通过String.valueOf()可以将其他类型数据转化为字符串。

char[] arr={'a', 'd', 'e'};
String s=String.valueOf(arr);

2、Java中的包装类

Java中的基本数据类型如int、double等都不具有对象的特性,为了像其他对象一样拥有自己的方法,Java为每个基本数据类型提供了包装类,像对象那样来操作基本数据类型。包装类的基本方法用于实现类型之间的相互转换。

Java包装类可以自动装箱/拆箱,即通过=运算符自动完成基本类型和包装类之间的类型转换。

                // 定义int类型变量,值为86
		int score1 = 86;
		// 使用int创建Integer包装类对象,手动装箱
		Integer score2=new Integer(score1);
                Integer score2=score1;    //自动装箱
		// 将Integer包装类转换为double类型
		double score3=score2.doubleValue();
		// 将Integer包装类转换为float类型
		float score4=score2.floatValue();
		// 将Integer包装类转换为int类型,手动拆箱
		int score5 =score2.intValue();
                int score5 = score2        // 自动拆箱
		// 将字符串转为int
		int score6 = Integer.parseInt("666");

基本类型与字符串之间的互相转换:

通过Integer.MAX_VALUE可以获得最大整数值

使用 java.util 包中的 Date 类可以创建时间对象,使用java.text 包中的 SimpleDateFormat 类可以将时间转化为所需格式的字符串,其中 “yyyy-MM-dd HH:mm:ss” 为预定义字符串, yyyy 表示四位年, MM 表示两位月份, dd 表示两位日期, HH 表示小时(使用24小时制), mm 表示分钟, ss 表示秒,这样就指定了转换的目标格式,最后调用 format() 方法将时间对象Date转换为指定的格式的字符串,反之parse()方法可以将普通字符串转化为Date对象。

java.util.Calendar 类可以更加方便地进行时间的处理,通过调用 getInstance() 静态方法获取一个 Calendar 对象,默认代表当前时间,可以通过c.getTime()将其转化为Date对象。Calendar对象的更多方法如下

Math 类位于 java.lang 包中,包含用于执行基本数学运算的方法, Math 类的所有方法都是静态方法,所以使用该类中的方法时,可以直接使用类名.方法名,如: Math.round();

int minNum=Math.min(2, 3);    //获取最小值
int maxNum=Math.max(2, 3);    //获取最大值

long round=Math.round(3.1415);      //四舍五入
double floor=Math.floor(3.1415);    //向下取整
double ceil=Math.ceil(3.1415);      //向上取整
double random=Math.random();        //取[0,1)之间的随机数

3、Java容器

在各种基本数据类型的基础上,Java使用集合类当作容器来储存具有相同属性的对象。通过集合类组织数据可以实现对特定数据的快速插入、删除与查询操作。而且与数组相比,集合的长度灵活可变,而且查找方式也不只有下标一种。Java中常见的集合类分为两个接口Collection和Map,其中Collection有三个子接口链表List、队列Queue、集Set,List常见的实现类为数组序列ArrayList,Queue实现类为LinkedList称为链表,Set实现类为哈希集。Collection中按照一个一个对象来存储数据,Map中按照键值对<key,value>来存储数据。

Collection接口规定了ArrayList、Set等具体实现类的接口方法,例如它们都使用add()方法来添加元素,因此一些方法名在各个类实现中是通用的。

ArrayList

ArrayList是类似于数组的容器,将对象储存进ArrayList之中便于组织和管理。通过add()方法可以将单个对象插入列表,addAll()可以将多个对象组成的子列表插入父列表中,插入时可以指定插入的位置,可以通过Arrays.asList()将数组转化为列表,通过toArray()方法可以将列表转为Object[]数组,可以向其中传入泛型参数从而返回特定类型的数组。

需要注意的是通过Arrays.asList()转化成的List长度是固定的,不能进行add()操作,会报错;我们可以将其作为子列表添加到一个新的List列表,然后再进行插入操作。

例如向列表courseList中插入Course对象:

public void addCourse(){
    Course c1=new Course(1,"数据结构");
    Course c2=new Course(2,"操作系统");
    Course[] cArr={new Course(3,"组成原理"),new Course(4,"计算机网络")};

    courseList.add(c1);                         // 向数组列表中添加对象
    courseList.add(0,c2);                 // 向指定位置添加对象
    courseList.addAll(Arrays.asList(cArr));     // 向列表中添加子列表,前加数字表示插入位置
    Course tmp=(Course)courseList.get(0);       // 从列表中取出对象
    Course[] courseArr=courseList.toArray(new Course[courseList.size()]);    // 转换为特定类型的数组
}

特别地,int[]与List<Integer>之间无法直接使用asList()/toArray()方法进行互相转换,可以经过如下流操作,或者遍历int[]逐个添加到List

int[] nums=new int[]{3,1,5,8};
//arr转list
List<Integer> numList = Arrays.stream(nums).boxed().collect(Collectors.toList());
//list转arr
int[] arr = numList.stream().mapToInt(Integer::valueOf).toArray();

通过size()方法可以获取列表长度,通过get()方法可以获取指定位置的对象,进而通过for循环遍历每个对象,也可以使用for each的方式遍历每个元素。还可以通过迭代器实现对每个对象的访问。值得注意的是,每个对象在列表中都是以Object对象的方式储存的,因此在取出之后需要通过强制类型转换为原来的对象类型,例如(Course)转为Course类的对象

    public void showCourse(){
        int listLength=courseList.size();           // 获取列表长度
        for (int i=0;i<listLength;i++) {
            Course c=(Course)courseList.get(i);     // 获取列表第i个元素
            System.out.println(c.name);
        }
    }

    public void iteratorCourse(){
        Iterator it=courseList.iterator();          // 获取迭代器
        while (it.hasNext()){                       // 如果仍有下一个元素
            Course c=(Course)it.next();             // 取出下一个元素
            System.out.println(c.name);
        }
    }

通过set()方法对列表指定位置的元素进行修改。通过remove()方法移除指定位置或者指定对象。通过removeAll()删除父列表中包含的所有子列表中的元素,通过clear()可以清空列表。

    public void modifyCourse(){
        courseList.set(2,new Course(5,"离散数学"));     // 修改2位置上的对象
    }

    public void removeCourse(){
        courseList.remove(3);               // 删除3位置上的对象
        Course c1= (Course) courseList.get(1);
        Course c2=(Course) courseList.get(2);
        courseList.remove(c1);                      // 删除指定对象
        Course[] cArr={c1,c2};
        courseList.removeAll(Arrays.asList(cArr));  // 删除courseList中所包含的cArr的元素
    }

通过contains()containsAll()方法判断List是否包含某个或者某几个对象,其实现原理是遍历List中的每个对象调用其equals()方法和目标对象进行比较,如果存在返回true,否则返回false。因此我们可以重写Course类的equals()方法,进而调用contains()方法判断List中是否包含指定Course对象。类似地indexOf()方法可以通过调用equals()找到元素在List中第一次出现的位置。

    // 重写Course类的equals()方法
    public boolean equals(Object o) {
        if (this == o) return true;     // 如果两个对象的地址相同,肯定相同
        if (!(o instanceof Course)) return false;
        Course course = (Course) o;
        return id == course.id &&       // 判断两个Course对象的id和name相同
                name.equals(course.name);
    }

    // 在CourseList中调用contains()判读是否包含某个对象
    public void containCourse(){
        Course nc=new Course(5,"数据结构");
        if(courseList.contains(nc)) {                     // 判断List中是否包含Course对象nc
            int index = courseList.indexOf(nc);           // 获取元素在List中的位置
            System.out.println("列表中包含该课程,位置:" + index);
        }
    }

之前提到集合中存放的都是对象的引用(Object),每次存入时集合会忽略对象的具体类型,有时存入其他类型对象则会在运行时出错,而且每次取出时则需要进行类型的强制转换还原回来。可以使用泛型规定某个集合只能存放特定类型或者其子类型的对象,这样就会在编译期间进行类型检查,而且在取出时可以直接返回特定类型的对象。注意泛型不能用于基本数据类型,例如List <int>会报错,而应该使用其包装类List <Integer>。

    // 创建元素类型为Course的列表
    public List<Course> courseList=new ArrayList<Course>();
    public void addCourse(){
        Course c=new Course(6,"数据结构");
        courseList.add(c);
//        courseList.add("字符串");    // 尝试向列表中添加非Course类型的对象,报错
        Course c2=courseList.get(0);        // 可以直接取出为Course类型对象
        System.out.println(c2.name);
    }

通过集合的工具类Collections.sort()方法可以实现对List对象的排序,其实现的原理是调用每个元素的compareTo()方法实现对象之间的比较进而排序。因此每个对象必须是可比较的类型,即必须实现了Comparable 接口的对象,如下所示首先定义可比较类Student,再定义学生列表studentLis添加学生对象后,调用Collections.sort()方法对列表进行排序,或者直接使用studentList.sort()。

public class Student implements Comparable<Student> {   // 定义Student类实现Comparable接口
    public String name;
    public int id;
    public Student(int id, String name) {
        this.name = name;
        this.id = id;
    }

    @Override
    public int compareTo(Student o) {        // 实现接口的方法,根据id大小对学生进行比较
        if (this.id>o.id){          // 如果大于o返回1
            return 1;
        }else if (this.id<o.id){    // 小于返回-1
            return -1;
        }else {                     // 等于返回0
            return 0;
        }
    }
}

public class ListSort {
    public List<Student> studentList=new ArrayList<Student>();    // 学生列表
    public void sortStudent(){
        Student s1=new Student(1011,"小明");
        Student s2=new Student(1005,"小赵");
        Student s3=new Student(1021,"小钱");
        Student[] sArr={s1,s2,s3};
        studentList.addAll(Arrays.asList(sArr));
        Collections.sort(studentList);                // 调用方法对学生列表进行排序
        for (Student s:studentList) {
            System.out.println(s.id+":"+s.name);
        }
    }
}

也可以在调用sort()方法时传入一个自定义的比较器对象Comparator,通过重写compare()方法来实现两个对象的比较。这里很明显可以看到上面的Comparable接口是被比较对象自身实现的,用于自身和其他对象比较;而Comparator是第三方对象实现的接口,用于比较两个对象。

// 自定义比较器类来实现两个Student对象的比较
public class StudentComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        if (o1.id>o2.id){          // 如果大于o返回1
            return 1;
        }else if (o1.id<o2.id){    // 小于返回-1
            return -1;
        }else {                     // 等于返回0
            return 0;
        }
    }
}
// 调用sort()方法时传入比较器
Collections.sort(studentList,new StudentComparator());

HashSet

哈希集是Set的一个实现类,与list不同,set中的元素是无序且不可以重复的。

和List一样,在Set中通过add()remove()等方法实现元素的增加删除等操作。由于Set是无序的,因此没有set()、get()方法实现在指定位置插入/获取元素,在遍历元素时通过for each、iterator来实现,而且每次遍历的结果顺序是不确定的。

注意HashSet中的contains()方法会首先调用对象的hashCode()方法比较哈希码,再调用equals()方法,两个都为true才会认为两个对象相同。

例如通过HashSet来存储学生所选课程

public class Student {
    public String name;
    public int id;
    public Set<Course> courses;     // 用set保存学生所选课程
    public Student(int id, String name) {
        this.name = name;
        this.id = id;
        this.courses=new HashSet<Course>();     //创建Hash集
    }

    public static void main(String[] args){
        Course c=new Course(1,"数据结构");
        Student s=new Student(101,"小明");
        s.courses.add(c);               // 向集中添加对象
        for (Course course:s.courses) {         // 遍历集
            System.out.println(course.name);
        }
    }
}

HashMap

Map以一一对应的键值对<key,value>的形式储存数据,通过映射关系可以实现key快速查找value,key值不能重复。Map也支持泛型Map<K,V>,注意K,V不能是Java类,而是包装类。

通过put(key,value)向Map中添加键值对,get(key)通过键获取值,remove(key)移除键。修改Map键值对也使用put()方法,新的键值对会覆盖原有的值。通过containsKey(key)方法可以返回Map中是否包含某个key值,containsValue(value)返回Map中是否包含某个值,它通过调用对象的equals()方法比较来返回是否存在。

还可以通过keySet()、values()、entrySet()方法分别获取Map的键、值、键值对,返回的键值对Entry仍然可以定义泛型类型。

    // 创建存储学生类的哈希Map
    public Map<Integer,String> studentMap=new HashMap<Integer, String>();
    public void addStudent(){
        Scanner input=new Scanner(System.in);
        System.out.print("请输入学生ID:");
        int studentID=input.nextInt();
        String s=studentMap.get(studentID);        // 根据key值获取对应的value
        if (s!=null){                              // 如果s不为空说明该key已经存在
            System.out.println("该学生ID已存在!");
        }else {
            System.out.print("请输入姓名:");
            String name=input.next();
            studentMap.put(studentID,name);     // 将<ID,name>键值对添加到Map中
        }
    }

    public void showStudent(){            //通过foreach遍历HashMap
        // 获取Map的键值对Entry并对其泛型进行定义
        Set<Map.Entry<Integer,String>> entrySet=studentMap.entrySet();
        for(Map.Entry<Integer,String> entry:entrySet){
            int key= entry.getKey();                    // 从Entry中获取key
            String name=entry.getValue();               // 从Entry中获取value
            System.out.println(key+":"+name);
        }
    }

    public void showStudent2(){            //通过迭代器遍历HashMap
      Iterator iter = studentMap.entrySet().iterator();
      while (iter.hasNext()) {
          Map.Entry entry = (Map.Entry) iter.next();
          Int key= entry.getKey();
          String name = entry.getValue();
            System.out.println(key+":"+name);
        }
  }

4、工具类

Stack

栈的创建和简单使用如下所示

        Stack<Integer> st = new Stack<>();      //新建栈
        st.push(3);
        int peek=st.peek();     //获取栈顶元素
        System.out.println(peek);
        int pop=st.pop();       //弹出栈顶元素
        System.out.println(pop);
        System.out.println(st.empty());     //判断栈是否为空

Queue

LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。队列的使用如下

        Queue<Integer> queue = new LinkedList<>();    //创建并初始化队列
        queue.offer(1);     //元素入队
        queue.offer(3);
        queue.offer(5);

        for(int num:queue)      //遍历队列
            System.out.println(num);
        int pNum=queue.peek()    //获取第一个元素
        int qNum=queue.poll();  //元素出队
        System.out.println(qNum);

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java数据类型转换详解

    一.基本数据类型阐述 Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. [注]JAVA没有unsigned类型 (1). 整数:int,short,byte,long (2). 浮点型:float,double (3). 字符:char (4). 布尔:boolean 基本型别     大小         最小值            最大值 void boolean     -----         -----             

  • JAVA中的基本数据类型

    byte: java中最小的数据类型.1字节/8位.-128(2^7)~127(2^7-1),默认值0. short: 短整型,2字节/16位,取值范围-32768(--2^15)~32767(2^15-1),默认值0 int: 整型,4字节/32位,取值范围-2147483648(-2^31)~2147483647(2^31-1),默认值0 long: 长整型,8字节/64位,-2^63(-2^63)~2^63-1(2^63-1),默认值0L float: 浮点型,4字节/32位,用于存储带小

  • Java 数据类型及类型转换的互相转换实例代码

    一.基本数据类型 java的数据类型可以分为两大类:基本类型和复合类型. 基本类型:整型(int,short,long,byte).浮点型(float,double).布尔型(boolean).和字符型(char) 复合类型:数组,类,接口 1.整型 各种整型数据所占空间及数的范围 数据类型 所占内存空间/位 数的范围 byte 8 -128~127 short 16 -32768~32767 int 32 -2^31~2^31-1 long 64 -2^63~2^63-1 整型以补码的形式存放

  • Java中的复合数据类型

    目录 1.Java字符串 2.Java中的包装类 3.Java容器 ArrayList HashSet HashMap 4.工具类 Stack Queue 1.Java字符串 在 Java 中字符串被作为 String 类型的对象处理. String 类位于 java.lang 包中,默认情况下该包自动导入. String对象创建后不会被修改,当我们修改某个字符串对象实际上是将原引用指向了新创建的内存空间.并且相同的字符串常量Java不会分配两个内存空间,而是将两个引用指向相同的空间. publ

  • 面向对象编程:Java中的抽象数据类型

    文章来源:互联网 作者:PaleSting/CSDN 在本文中,我们将考察Java中的数据类型,但是我们将介绍抽象数据类型(ADT)的概念.我们还将通过介绍Java Collections Framework(Java 集合架构)来学习Java定义的一些ADT. ADT 一个ADT是一个仅由保存的数据类型和可能在这个数据类型上进行的操作定义的.开发者们只能通过ADT的操作方法来访问ADT的属性,而且他们不会知道这个数据类型内部各种操作是如何实现的. 在Java中,我们常常使用一个接口来给出一个操

  • 详解Java中“==”与equals()的区别

    Java中"=="与equals()的区别 对于关系操作符"==",<Java编程思想>中是这样描述的:"关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系".这里的操作数的"值"值得我们注意.对于8种基本数据类型(boolean,byte,char,short,int,float,double,long),它们的变量直接存储的就是"值".所以,我们用"==&q

  • 详解Java中的数组与字符串相关知识

    Java数组的定义和使用 如果希望保存一组有相同类型的数据,可以使用数组. 数组的定义和内存分配 Java 中定义数组的语法有两种: type arrayName[]; type[] arrayName; type 为Java中的任意数据类型,包括基本类型和组合类型,arrayName为数组名,必须是一个合法的标识符,[ ] 指明该变量是一个数组类型变量.例如: int demoArray[]; int[] demoArray; 这两种形式没有区别,使用效果完全一样,读者可根据自己的编程习惯选择

  • java中数组的定义及使用方法(推荐)

    数组:是一组相关变量的集合 数组是一组相关数据的集合,一个数组实际上就是一连串的变量,数组按照使用可以分为一维数组.二维数组.多维数组 数据的有点 不使用数组定义100个整形变量:int i1;int i2;int i3 使用数组定义 int i[100]; 数组定义:int i[100];只是一个伪代码,只是表示含义的 一维数组 一维数组可以存放上千万个数据,并且这些数据的类型是完全相同的, 使用java数组,必须经过两个步骤,声明数组和分配内存给该数组, 声明形式一 声明一维数组:数据类型

  • Java中long类型与Long类型的区别和大小比较详解

    前言 最近在学习java,接触到了long类型,发现网上这方面的资料较乱,所以决定总结一下,在Java中我们经常要做一些判断,而对于判断的话,用的最多的便是">"."=="."<"的比较,这里我们进行一个Long类型数据和long类型数据的比较大小的讲解.话不多说了,来一起看看详细的介绍吧. Java中Long和long的区别 Java的数据类型分为两种: 1.基本类型:byte(8),short(16),int(32),long(6

  • 详解Java中int和Integer的区别

    基本数据类型和引用类型 Java是面向对象的编程语言,一切都是对象,但是为了编程的方便还是引入了基本数据类型,为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换,对应如下: 原始类型:boolean,char,byte,short,int,long,float,double 包装类型:Boolean,Character,Byte

  • java中char对应的ASCII码的转化操作

    java中,char类型变量可以强制转化为int类型变量,int类型变量也可以强制转化成char类型的变量: char c='a'; int i=98; System.out.println((int)c); System.out.println((char)i); 对于数组类型,其下标为int类型,所以可以直接使用char类型变量,默认强制转换: int[] array=new int[100]; for(int i=0;i<array.length;i++){ array[i]=i; } c

  • Java中的纸老虎之泛型

    目录 一. 泛型的定义 二. 为什么要用到泛型 三. 泛型的写法 四. 泛型的使用实例 1. 求最大值 2. 优化 五. 通配符 1. 基本写法 2. 上界 3. 下界 六. 泛型的限制 泛型,其实算是Java当中比较难的语法了,很多人一开始都对其一知半解,也很害怕阅读带泛型的源码,虽然看起来语法很难,但当你理解后会觉得很简单,其实只是一个纸老虎罢了.下面,我将会用非常简单易懂的方式带你去理解它,相信你在认真看完后会有非常大的收获,从此不会再畏惧它! 一. 泛型的定义 这里大家可以不必去看网上的

随机推荐