IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> List集合排序总结 -> 正文阅读

[数据结构与算法]List集合排序总结

目录

问题现象

解决方法:

1、Collections.sort(java对象)

?2、Collections.sort(java对象集合, new Comparator<>() {});

拓展:

3、list.stream().sorted()

拓展:

总结:

4、List排序

4.1、List的单条件升序(默认)排序

4.2、List的单条件降序排序

?4.3、List的多条件排序


问题现象

????????今天在项目中相对List集合进行按需求的排序,因此打算总结一下各种情况下的List排序的代码写法?


解决方法:

自己总结了以下,list集合的排序主要有以下几种排序方式:

1、Collections.sort(java对象)

? ? ? ? 这种方式需要满足以下条件:
? ? ? ? 1.1、list集合中元素的数据类型是一个java对象;

? ? ? ? 1.2、该java对象必须实现Comparable类;

? ? ? ? 1.3、重写compareTo方法;

????????其中?compareTo 方法用于指示当前元素与其他元素的比较规则,一般都是以 a - b 的形式返回int类型,表示排序规则为从 a 到 b 排序,其逻辑理解就是:如果compareTo方法返回值小于0,则当前元素往前放,大于0,则往后放。

Student实体类:

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Student implements Comparable<Student> {

	private String name;

	private int age;

	@Override
	public int compareTo(Student stu) {
		return getAge() - stu.getAge();
	}
}

测试:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1=new Student("小米",1);
		Student stu2=new Student("小王",2);
		Student stu3=new Student("小明",3);

		List<Student> list=new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);

		System.out.println("排序后:");
		Collections.sort(list);
		System.out.println(list);
	}
}

打印结果:

?2、Collections.sort(java对象集合, new Comparator<>() {});

? ? ? ? 这种方式与需要满足以下条件:
? ? ? ? 1.1、list集合中元素的数据类型是一个java对象;

? ? ? ? 1.2、重写compare方法;

Comparator 和 Comparable 的区别和理解:

Comparator 可以看成是外部比较器,因为它是先有list集合,然后再对list集合用比较器去排序;

Comparable 可以看成是内部比较器,因为它是直接在java对象实现类添加了比较器,因此是先有比较器,然后再对list集合用比较器去排序;

从上面两点,也可以推测出?Comparable 的排序算法的效率应该是比 Comparator 要高效的。

Comparator :使用了匿名内部类来构建了一个Comparator比较器对象,从而实现排序,优点是:不需要在创建java对象时,实现 Comparable 接口,缺点是效率比 Comparable? 要低一些。

Student实体类:

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Student{

	private String name;

	private int age;

}

测试:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1 = new Student("小米", 1);
		Student stu2 = new Student("小王", 2);
		Student stu3 = new Student("小明", 3);

		List<Student> list = new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);

		System.out.println("排序后:");
		Collections.sort(list, new Comparator<Student>() {
			@Override
			public int compare(Student stu1, Student stu2) {
				return stu1.getAge() - stu2.getAge();
			}
		});
		System.out.println(list);
	}
}

打印结果:


拓展:

????????根据 JAVA8 的 lambda 表达式上面Compartor比较器的代码可以简写成以下代码:

		Collections.sort(list, (stu11, stu21) -> stu11.getAge() - stu21.getAge());

????????再进一步简化成如下代码:

    Collections.sort(list, Comparator.comparingInt(Student::getAge));
或
    Collections.sort(list, Comparator.comparing(Student::getAge));

通过查询 comparing开头的方法,可以看见:

经过我的测试发现comparing兼容了下面三种基于整型数据的方法:

显然用comparing很省事,但是一般兼容性越高,效率也就越低,可以推测出comparing方法内部肯定是有一重判断了参数的数据类型的逻辑,这会降低代码执行效率;因此,如果是整型数据的话,建议使用上面三种与数据类型对应的方法,而如果是字符串的话,就使用comparing。

简化后:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1 = new Student("小米", 1);
		Student stu2 = new Student("小王", 2);
		Student stu3 = new Student("小明", 3);

		List<Student> list = new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);

		System.out.println("排序后:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge));
		System.out.println(list);
	}
}

打印结果:

可以看出这是升序排序的,那么如何降序呢?

由于降序=升序的倒序,所以可以使用倒序的方法【.reversed()】实现降序:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1 = new Student("小米", 1);
		Student stu2 = new Student("小王", 2);
		Student stu3 = new Student("小明", 3);

		List<Student> list = new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);

		System.out.println("排序后:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge));
		System.out.println(list);
        System.out.println("倒序后:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).reversed());
		System.out.println(list);
	}
}

打印结果:

多条件排序:

Student实体类:

@Data
@AllArgsConstructor
public class Student{

	private String name;

	private int age;

	private double grade;

	private int tall;

}

测试:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1 = new Student("小米", 20, 95.0, 175);
		Student stu2 = new Student("小王", 20, 90.5, 175);
		Student stu3 = new Student("小明", 20, 90.0, 180);

		List<Student> list = new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);
		System.out.println("排序后:");
		Collections.sort(list, Comparator.comparingInt(Student::getTall));
		System.out.println(list);
		System.out.println("倒序后:");
		Collections.sort(list, Comparator.comparingInt(Student::getTall).reversed());
		System.out.println(list);

		System.out.println("1.按年龄升序、分数升序、身高升序排序:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).thenComparingInt(Student::getTall));
		System.out.println(list);
		System.out.println("2.按年龄升序、分数升序、身高降序序排序:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).thenComparingInt(Student::getTall).reversed());
		System.out.println(list);
		System.out.println("3.按年龄升序、分数降序、身高升序排序:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).reversed().thenComparingInt(Student::getTall));
		System.out.println(list);
		System.out.println("4.按年龄升序、分数降序、身高降序序排序:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).reversed().thenComparingInt(Student::getTall).reversed());
		System.out.println(list);
		System.out.println("5.按年龄升序、身高升序、分数升序排序:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).thenComparingInt(Student::getTall).thenComparingDouble(Student::getGrade));
		System.out.println(list);
		System.out.println("6.按年龄升序、身高升序、分数降序序排序:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).thenComparingInt(Student::getTall).thenComparingDouble(Student::getGrade).reversed());
		System.out.println(list);
		System.out.println("7.按年龄升序、身高降序、分数升序排序:");
		Collections.sort(list, Comparator.comparingInt(Student::getAge).thenComparingInt(Student::getTall).reversed().thenComparingDouble(Student::getGrade));
		System.out.println(list);
		System.out.println("8.按年龄升序、身高降序、分数降序序排序:");
		Collections.sort(list, Comparator.comparing(Student::getAge).thenComparing(Student::getGrade).reversed().thenComparing(Student::getTall).reversed());
		System.out.println(list);
	}
}

打印结果:


3、list.stream().sorted()

JAVA8 之后,引入了stream流操作,可以极大提高集合的链式操作效率,关于stream流操作不太清楚的小伙伴,可以自行查阅资料,比较简单,这里就不再拓展了;

这里要提的是stream流操作中的?sorted()方法可以用于排序,其逻辑原理和上面第二种 Comparator?的排序方式是一样的。

这种方式与需要满足以下条件:
? ? ? ? 1.1、list集合中元素的数据类型是一个java对象;

? ? ? ? 1.2、引入stream流操作规范;

优点:排序算法效率高。

?Student实体类:

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Student{

	private String name;

	private int age;

}

测试:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1 = new Student("小米", 1);
		Student stu2 = new Student("小王", 2);
		Student stu3 = new Student("小明", 3);

		List<Student> list = new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);

		System.out.println("排序后:");
		list = list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
		System.out.println(list);
	}
}

打印结果:

同样的以使用倒序的方法【.reversed()】实现降序:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1 = new Student("小米", 1);
		Student stu2 = new Student("小王", 2);
		Student stu3 = new Student("小明", 3);

		List<Student> list = new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);

		System.out.println("排序后:");
		list = list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("倒序后:");
		list = list.stream().sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList());
		System.out.println(list);
	}
}

打印结果:


拓展:

? ? ? ? 很多使用不仅需要对单一字段进行排序,还需要多个字段排序,因此多条件排序很重要!

多条件排序:

?Student实体类:

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Student{

	private String name;

	private int age;

	private double grade;

	private int tall;

}

测试:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class TestUtil {
	public static void main(String[] args) {
		Student stu1 = new Student("小米", 20, 95.0, 175);
		Student stu2 = new Student("小王", 20, 90.5, 175);
		Student stu3 = new Student("小明", 20, 90.0, 180);

		List<Student> list = new ArrayList<>();
		list.add(stu2);
		list.add(stu1);
		list.add(stu3);

		System.out.println("排序前:");
		System.out.println(list);

		System.out.println("1.按年龄升序、分数升序、身高升序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).thenComparingInt(Student::getTall)).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("2.按年龄升序、分数升序、身高降序序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).thenComparingInt(Student::getTall).reversed()).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("3.按年龄升序、分数降序、身高升序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).reversed().thenComparingInt(Student::getTall)).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("4.按年龄升序、分数降序、身高降序序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingDouble(Student::getGrade).reversed().thenComparingInt(Student::getTall).reversed()).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("5.按年龄升序、身高升序、分数升序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingInt(Student::getTall).thenComparingDouble(Student::getGrade)).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("6.按年龄升序、身高升序、分数降序序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingInt(Student::getTall).thenComparingDouble(Student::getGrade).reversed()).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("7.按年龄升序、身高降序、分数升序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingInt(Student::getTall).reversed().thenComparingDouble(Student::getGrade)).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("8.按年龄升序、身高降序、分数降序序排序:");
		list = list.stream().sorted(Comparator.comparingInt(Student::getAge).thenComparingInt(Student::getTall).reversed().thenComparingDouble(Student::getGrade).reversed()).collect(Collectors.toList());
		System.out.println(list);
	}
}

打印结果:

???????


总结:

????????推荐使用第三种排序方法,因为stream流操作排序效率最高


4、List<JSONObject>排序

这个其实才是这篇文章的重点,很多时候为了方便,我们会用到JSONObject或者Map对象去接收数据库返回的结果集;

? ? ? ? 1、例如当数据库表过多的时候,我们并不想为每个表都创建一个java实体类去接收数据;

? ? ? ? 2、尤其是当我们想动态的查询出自己想要的数据,而结果中的字段名很可能并不是固定的;

? ? ? ? 3、当然还有很多其他的复杂情况。。。

当我们使用的这一类不是由java实体类组成的List集合的时候,上面的那三种方法显然是未必适用的,于是为了应对这种情况下的排序需求,经过我的测试,总结出了下面3种情况和方法:

4.1、List<JSONObject>的单条件升序(默认)排序

大多数情况下,我们需要排序的时候,都是单条件排序,所以这是最基本的排序方法,基本上和第三种排序方式(list.stream().sorted())中的单条件排序的写法很类似,所以比较简单。

测试:

public class TestDemoUtil {
	public static void main(String[] args) {
		List<JSONObject> list = new ArrayList<>();
		JSONObject jsonObject1 = new JSONObject();
		JSONObject jsonObject2 = new JSONObject();
		JSONObject jsonObject3 = new JSONObject();

		jsonObject1.put("name", "小米");
		jsonObject1.put("age", 20);
		jsonObject1.put("grade", 95.0);
		jsonObject1.put("tail", 175);

		jsonObject2.put("name", "小王");
		jsonObject2.put("age", 20);
		jsonObject2.put("grade", 90.5);
		jsonObject2.put("tail", 175);

		jsonObject3.put("name", "小明");
		jsonObject3.put("age", 20);
		jsonObject3.put("grade", 90.0);
		jsonObject3.put("tail", 180);
		list.add(jsonObject1);
		list.add(jsonObject2);
		list.add(jsonObject3);

		System.out.println("排序前:");
		System.out.println(list);
		System.out.println("按成绩升序排序后:");
		list = list.stream().sorted(Comparator.comparingDouble(o -> o.getDoubleValue("grade"))).collect(Collectors.toList());
		System.out.println(list);
	}
}

打印结果:

4.2、List<JSONObject>的单条件降序排序

????????需要注意的是,和上面提到的第三种排序方式(list.stream().sorted())不同,在对集合进行降序排序的时候,无法直接在链式链式调用后面加上【.reversed()】来实现降序了;经过测试发现list.stream().sorted()对于JSONObject这一类非自定义的java对象无法完美是使用链式调用了,原因很可能是因为JSONObject这一类对象没有确定属性的getter/setter方法,所以下面这种写法会在编译的时候报错:

		list = list.stream().sorted(Comparator.comparingDouble(o -> o.getDoubleValue("grade")).reversed()).collect(Collectors.toList());

猜测原因应该是因为在链式调用中 getDoubleValue 会被识别为?JSONObject对象中 doubleValue属性对应的 getter方法,而该对象根本没有这个属性,所以就报错了,所以还是那句话链式调用的规则,并不适用于没有确定属性的这一类对象。

所以可以使用下面这种写法来解决降序的问题:

测试:

public class TestDemoUtil {
	public static void main(String[] args) {
		List<JSONObject> list = new ArrayList<>();
		JSONObject jsonObject1 = new JSONObject();
		JSONObject jsonObject2 = new JSONObject();
		JSONObject jsonObject3 = new JSONObject();

		jsonObject1.put("name", "小米");
		jsonObject1.put("age", 20);
		jsonObject1.put("grade", 95.0);
		jsonObject1.put("tail", 175);

		jsonObject2.put("name", "小王");
		jsonObject2.put("age", 20);
		jsonObject2.put("grade", 90.5);
		jsonObject2.put("tail", 175);

		jsonObject3.put("name", "小明");
		jsonObject3.put("age", 20);
		jsonObject3.put("grade", 90.0);
		jsonObject3.put("tail", 180);
		list.add(jsonObject1);
		list.add(jsonObject2);
		list.add(jsonObject3);

		System.out.println("排序前:");
		System.out.println(list);
		System.out.println("按成绩升序排序后:");
		list = list.stream().sorted(Comparator.comparingDouble(o -> o.getDoubleValue("grade"))).collect(Collectors.toList());
		System.out.println(list);
		System.out.println("按成绩降序排序后:");
		list = list.stream().sorted((o1, o2) -> o2.getDoubleValue("grade") - o1.getDoubleValue("grade") > 0 ? 1 : -1).collect(Collectors.toList());
		System.out.println(list);
	}
}

打印结果:

?4.3、List<JSONObject>的多条件排序

多条件排序是重点,虽然很多时候我们只需要单条件排序;但多条件排序的写法才是重点,因为这种写法是最基础的,也是兼容最强的。

测试:

public class TestDemoUtil {
	public static void main(String[] args) {
		List<JSONObject> list = new ArrayList<>();
		JSONObject jsonObject1 = new JSONObject();
		JSONObject jsonObject2 = new JSONObject();
		JSONObject jsonObject3 = new JSONObject();

		jsonObject1.put("name", "小米");
		jsonObject1.put("age", 20);
		jsonObject1.put("grade", 95.0);
		jsonObject1.put("tail", 175);

		jsonObject2.put("name", "小王");
		jsonObject2.put("age", 20);
		jsonObject2.put("grade", 90.5);
		jsonObject2.put("tail", 175);

		jsonObject3.put("name", "小明");
		jsonObject3.put("age", 20);
		jsonObject3.put("grade", 90.0);
		jsonObject3.put("tail", 180);
		list.add(jsonObject1);
		list.add(jsonObject2);
		list.add(jsonObject3);

		System.out.println("排序前:");
		System.out.println(list);
		System.out.println("按成绩排序后:");
		list = list.stream().sorted(Comparator.comparingDouble(o -> o.getDoubleValue("grade"))).collect(Collectors.toList());
		System.out.println(list);

		System.out.println("1.按年龄升序、分数升序、身高升序排序:");
		list = list.stream().sorted((o1, o2) -> {
			int value = o1.getIntValue("age") - o2.getIntValue("age");
			if ( value == 0 ) {
				double v = o1.getDoubleValue("grade") - o2.getDoubleValue("grade");
				if ( v == 0.0 ) {
					return o1.getIntValue("tail") - o2.getIntValue("tail");
				}
				return v > 0.0 ? 1 : -1;
			}
			return value;
		}).collect(Collectors.toList());
		System.out.println(list);

		System.out.println("2.按年龄升序、分数降序、身高升序排序:");
		list = list.stream().sorted((o1, o2) -> {
			int value = o1.getIntValue("age") - o2.getIntValue("age");
			if ( value == 0 ) {
				double v = o2.getDoubleValue("grade") - o1.getDoubleValue("grade");
				if ( v == 0.0 ) {
					return o1.getIntValue("tail") - o2.getIntValue("tail");
				}
				return v > 0.0 ? 1 : -1;
			}
			return value;
		}).collect(Collectors.toList());
		System.out.println(list);

		System.out.println("3.按年龄升序、身高升序、分数降序排序:");
		list = list.stream().sorted((o1, o2) -> {
			int value = o1.getIntValue("age") - o2.getIntValue("age");
			if ( value == 0 ) {
				value = o1.getIntValue("tail") - o2.getIntValue("tail");
				if ( value == 0 ) {
					return o2.getDoubleValue("grade") - o1.getDoubleValue("grade") > 0.0 ? 1 : -1;
				}
				return value;
			}
			return value;
		}).collect(Collectors.toList());
		System.out.println(list);
	}
}

上面的代码可以通过提取公共方法,来提高代码复用率,由于和文章主题无关,这里就不进一步优化了。

打印结果:

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:24:47  更:2022-04-15 00:26:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:16:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码