kafka系列五、kafka常用java API
引入maven包
- <dependency>
- <groupId>org.apache.kafka</groupId>
- <artifactId>kafka-clients</artifactId>
- <version>0.11.0.1</version>
- </dependency>
一、同步发送消息
1、创建topic:
- ./bin/kafka-topics.sh --create --zookeeper 127.0.0.1:2181 --partitions 3 --replication-factor 1 --topic test-syn
2、代码
- package com.example.demo.test;
- import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;- import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;- public class SynProducer {
private static Properties getProps(){
Properties props = new Properties();
props.put("bootstrap.servers", "47.52.199.51:9092");
props.put("acks", "all"); // 发送所有ISR
props.put("retries", 2); // 重试次数
props.put("batch.size", 16384); // 批量发送大小
props.put("buffer.memory", 33554432); // 缓存大小,根据本机内存大小配置
props.put("linger.ms", 1000); // 发送频率,满足任务一个条件发送
props.put("client.id", "producer-syn-1"); // 发送端id,便于统计
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
return props;
}- public static void main(String[] args) {
KafkaProducer<String, String> producer = new KafkaProducer<>(getProps());
for(int i=0; i< 1000; i++){
// 三个参数,topic,key:用户分配partition,value:发送的值
ProducerRecord<String, String> record = new ProducerRecord<>("test-syn", "topic_"+i,"test-syn-"+i);
Future<RecordMetadata> metadataFuture = producer.send(record);
RecordMetadata recordMetadata = null;
try {
recordMetadata = metadataFuture.get();
System.out.println("发送成功!");
System.out.println("topic:"+recordMetadata.topic());
System.out.println("partition:"+recordMetadata.partition());
System.out.println("offset:"+recordMetadata.offset());
} catch (InterruptedException|ExecutionException e) {
System.out.println("发送失败!");
e.printStackTrace();
}
}- producer.flush();
producer.close();
}
}
3、测试
1、创建consumer
- ./bin/kafka-console-consumer.sh --bootstrap-server 47.52.199.52: --topic test-syn --group test- --from-beginning
2、运行程序
二、异步发送消息
- package com.example.demo.test;
- import org.apache.kafka.clients.producer.KafkaProducer;
- import org.apache.kafka.clients.producer.ProducerRecord;
- import java.util.Properties;
- public class ASynProducer {
- private static Properties getProps(){
- Properties props = new Properties();
- props.put("bootstrap.servers", "47.52.199.51:9092");
- props.put("acks", "all"); // 发送所有ISR
- props.put("retries", 2); // 重试次数
- props.put("batch.size", 16384); // 批量发送大小
- props.put("buffer.memory", 33554432); // 缓存大小,根据本机内存大小配置
- props.put("linger.ms", 1000); // 发送频率,满足任务一个条件发送
- props.put("client.id", "producer-asyn-1"); // 发送端id,便于统计
- props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
- props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
- return props;
- }
- public static void main(String[] args) {
- KafkaProducer<String, String> producer = new KafkaProducer<>(getProps());
- for(int i=0; i< 1000; i++){
- ProducerRecord<String, String> record = new ProducerRecord<>("test-asyn", "topic_"+i,"test-asyn-"+i);
- // 相比同步发送,异步发送需要传入callback,发送结果回来回调callback方法
- producer.send(record, (recordMetadata, e) -> {
- if(e != null){
- System.out.println("发送失败!");
- e.printStackTrace();
- }else {
- System.out.println("发送成功!");
- System.out.println("topic:"+recordMetadata.topic());
- System.out.println("partition:"+recordMetadata.partition());
- System.out.println("offset:"+recordMetadata.offset());
- }
- });
- }
- producer.flush();
- producer.close();
- }
- }
三、及时发送消息
相比前两种方式,该方式不关心结果,只管发送,所以比较快。
- package com.example.demo.test;
- import org.apache.kafka.clients.producer.KafkaProducer;
- import org.apache.kafka.clients.producer.ProducerRecord;
- import java.util.Properties;
- public class FireProducer {
- private static Properties getProps(){
- Properties props = new Properties();
- props.put("bootstrap.servers", "47.52.199.51:9092");
- props.put("acks", "all"); // 发送所有ISR
- props.put("retries", 2); // 重试次数
- props.put("batch.size", 16384); // 批量发送大小
- props.put("buffer.memory", 33554432); // 缓存大小,根据本机内存大小配置
- props.put("linger.ms", 1000); // 发送频率,满足任务一个条件发送
- props.put("client.id", "producer-syn-1"); // 发送端id,便于统计
- props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
- props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
- return props;
- }
- public static void main(String[] args) {
- KafkaProducer<String, String> producer = new KafkaProducer<>(getProps());
- for(int i=0; i< 1000; i++){
- ProducerRecord<String, String> record = new ProducerRecord<>("test-syn", "topic_"+i,"test-syn-"+i);
- // 不关心发送结果
- producer.send(record);
- }
- producer.flush();
- producer.close();
- }
- }
四、自动提交offset
- package com.example.demo.consumer;
- import org.apache.kafka.clients.consumer.ConsumerRecord;
- import org.apache.kafka.clients.consumer.ConsumerRecords;
- import org.apache.kafka.clients.consumer.KafkaConsumer;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Properties;
- /**
- * @author 王柱星
- * @version 1.0
- * @title
- * @time 2018年12月11日
- * @since 1.0
- */
- public class AutoCommitConsumer {
- private static Properties getProps(){
- Properties props = new Properties();
- props.put("bootstrap.servers", "47.52.199.52:9092");
- props.put("group.id", "test_3");
- props.put("session.timeout.ms", 30000); // 如果其超时,将会可能触发rebalance并认为已经死去,重新选举Leader
- props.put("enable.auto.commit", "true"); // 开启自动提交
- props.put("auto.commit.interval.ms", "1000"); // 自动提交时间
- props.put("auto.offset.reset","earliest"); // 从最早的offset开始拉取,latest:从最近的offset开始消费
- props.put("client.id", "producer-syn-1"); // 发送端id,便于统计
- props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- return props;
- }
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- // 拉取任务超时时间
- for(;;){
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- }
- }
- }
- }
五、同步提交
同步提交,提交后broke会阻塞等结果返回,在成功提交或碰到无怯恢复的错误之前,commitSync()会一直重试
- package com.example.demo.consumer;
- import org.apache.kafka.clients.consumer.ConsumerRecord;
- import org.apache.kafka.clients.consumer.ConsumerRecords;
- import org.apache.kafka.clients.consumer.KafkaConsumer;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Properties;
- /**
- * @author 王柱星
- * @version 1.0
- * @title
- * @time 2018年12月11日
- * @since 1.0
- */
- public class CommitConsumer {
- private static Properties getProps(){
- Properties props = new Properties();
- props.put("bootstrap.servers", "47.52.199.51:9092");
- props.put("group.id", "test_3");
- props.put("session.timeout.ms", 30000); // 如果其超时,将会可能触发rebalance并认为已经死去,重新选举Leader
- props.put("enable.auto.commit", "false"); // 开启自动提交
- props.put("auto.commit.interval.ms", "1000"); // 自动提交时间
- props.put("auto.offset.reset","earliest"); // 从最早的offset开始拉取,latest:从最近的offset开始消费
- props.put("client.id", "consumer-2"); // 发送端id,便于统计
- props.put("max.poll.records","1000"); // 每次批量拉取条数
- props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- return props;
- }
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- // 当前批次offset
- consumer.commitSync();
- }
- }
- }
- }
六、异步提交
commitAsync()方法提交最后一个偏移量。在成功提交或碰到无怯恢复的错误之前,commitSync()会一直重试,但是commitAsync()不会,这也是commitAsync()不好的一个地方。它之所以不进行重试,是因为在它收到服务器响应的时候, 可能有一个更大的偏移量已经提交成功。假设我们发出一个请求用于提交偏移量2000,这个时候发生了短暂的通信问题,服务器收不到请求,自然也不会作出任何响应。与此同时,我们处理了另外一批消息,并成功提交了偏移量3000。如果commitAsync()重新尝试提交偏移量2000 ,它有可能在偏移量3000之后提交成功。系统会记录最后提交的偏移量,这个时候如果发生再均衡,就会出现重复消息,会从2000开始。
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- // 当前批次offset
- consumer.commitAsync();
- }
- }
- }
异步提交支持回调方法,可以记录提交错误的值
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- // 当前批次offset
- consumer.commitAsync((map, e) -> {
- if(e != null){
- System.out.println("提交失败:"+map.get(""));
- }
- });
- }
- }
- }
七、同步和异步组合提交
- package com.example.demo.consumer;
- import org.apache.kafka.clients.consumer.ConsumerRecord;
- import org.apache.kafka.clients.consumer.ConsumerRecords;
- import org.apache.kafka.clients.consumer.KafkaConsumer;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Properties;
- /**
- * @author 王柱星
- * @version 1.0
- * @title
- * @time 2018年12月11日
- * @since 1.0
- */
- public class CommitAsynCallbackConsumer {
- private static Properties getProps(){
- Properties props = new Properties();
- props.put("bootstrap.servers", "47.52.199.51:9092");
- props.put("group.id", "test_4");
- props.put("session.timeout.ms", 30000); // 如果其超时,将会可能触发rebalance并认为已经死去,重新选举Leader
- props.put("enable.auto.commit", "false"); // 开启自动提交
- props.put("auto.commit.interval.ms", "1000"); // 自动提交时间
- props.put("auto.offset.reset","earliest"); // 从最早的offset开始拉取,latest:从最近的offset开始消费
- props.put("client.id", "consumer-3"); // 发送端id,便于统计
- props.put("max.poll.records","200"); // 每次批量拉取条数
- props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- return props;
- }
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- // 当前批次offset
- consumer.commitAsync((map, e) -> {
- if(e != null){
- System.out.println("提交失败:"+map.get(""));
- }
- });
- }
- }
- }
- }
八、提交到特定的partition、偏移量
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- Map<TopicPartition, OffsetAndMetadata> offsets = new HashMap<>();
- // 指定topic 、partition
- TopicPartition topicPartition = new TopicPartition("producer-syn",0);
- // 指定offset
- OffsetAndMetadata offsetAndMetadata = new OffsetAndMetadata(100);
- // 可以提交多个topic
- offsets.put(topicPartition, offsetAndMetadata);
- // 提交offset
- consumer.commitSync(offsets);
- }
- }
- }
为提高消费吞吐量,可使用线程处理,消费者只负责接收消息,由线程池处理。
九、从特定偏移量处开始消费
前面都是consumer.poll()之后读取该批次的消息,kafka还提供了从分区的开始或者末尾读消息的功能:
- seekToEnd(Collection<TopicPartition> partitions)
- seekToBeginning(Collection<TopicPartition> partitions)
另外kafka还提供了从指定偏移量处读取消息,可以通过seek()方法来处理:
- // 只有先pull一次,seek才会生效,启动后第一次拉取不返回数据
- seek(TopicPartition partition, long offset)
示例:
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- TopicPartition topicPartition = new TopicPartition("producer-syn",0);
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- // 只有先pull一次,seek才会生效,启动后第一次拉取不返回数据
- consumer.seek(topicPartition,100L);
- // new ArrayList<>(topicPartition)
- List list = new ArrayList<>();
- list.add(topicPartition);
- // consumer.seekToEnd(list);
- // consumer.seekToBeginning(list);
- consumer.commitSync();
- }
- }
- }
十、从特定时间开始消费
- offsetsForTimes(java.util.Map<TopicPartition,java.lang.Long>)
- 入参:parttition、时间戳
- 返回:响应的offset
- 调用 seek(TopicPartition partition, long offset)开始消费
示例:
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- TopicPartition topicPartition = new TopicPartition("producer-syn",0);
- List<String> topics = new ArrayList<>();
- topics.add("producer-syn");
- consumer.subscribe(topics);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- Map<TopicPartition, Long> timestampsToSearch = new HashMap<>();
- // 通过时间戳获取offset
- timestampsToSearch.put(topicPartition,1544594780946L);
- Map<TopicPartition, OffsetAndTimestamp> timestampMap = consumer.offsetsForTimes(timestampsToSearch);
- // 指定offset
- consumer.seek(topicPartition,timestampMap.get(topicPartition).offset());
- consumer.commitSync();
- }
- }
- }
其他场景:
通过时间戳查询指定分区的offsets,前后两个时间戳就是指定的时间段,所有分区相加就是指定的主题。所以可以通过时间戳查询指定分区的offsets方法来查询指定时间段内指定主题的偏移量。结果可以用来核对生产或者同步的消息数量。
十一、监听rebalance提交
前面我们说过当发生consumer退出或者新增,partition新增的时候会触发再均衡。那么发生再均衡的时候如果某个consumer正在消费的任务没有消费完该如何提交当前消费到的offset呢?kafka提供了再均衡监听器,在发生再均衡之前监听到,当前consumer可以在失去分区所有权之前处理offset关闭句柄等。
消费者API中有一个()方法:
- subscribe(Collection<TopicPartition> var1, ConsumerRebalanceListener var2);
ConsumerRebalanceListener对象就是监听器的接口对象,我们需要实现自己的监听器继承该接口。接口里面有两个方法需要实现:
- void onPartitionsRevoked(Collection<TopicPartition> var1);
- void onPartitionsAssigned(Collection<TopicPartition> var1);
第一个方法会在再均衡开始之前和消费者停止读取消息之后被调用。如果在这里提交偏移量,下一个接管分区的消费者就知道该从哪里开始读取了。
第二个会在重新分配分区之后和消费者开始读取消息之前被调用。
示例:
- public static void main(String[] args) {
- KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps()) ;
- List<String> topics = new ArrayList<>();
- topics.add("test-syn");
- // 指定offset
- Map<TopicPartition, OffsetAndMetadata> currentOffset = new HashMap<>();
- consumer.subscribe(topics, new ConsumerRebalanceListener() {
- @Override
- public void onPartitionsRevoked(Collection<TopicPartition> collection) {
- System.out.println("发生rebalance!提交:"+currentOffset);
- consumer.commitAsync(currentOffset,null);
- }
- @Override
- public void onPartitionsAssigned(Collection<TopicPartition> collection) {
- }
- });
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- Long offset = 0L;
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- offset = consumerRecord.offset();
- }
- TopicPartition topicPartition = new TopicPartition("test-syn",0);
- OffsetAndMetadata offsetAndMetadata = new OffsetAndMetadata(offset);
- currentOffset.put(topicPartition, offsetAndMetadata);
- consumer.commitSync();
- }
- }
十二、主动分配分区消费
到目前为止我们讨论的都是消费者群组,分区被自动分配给群组的消费者,群组的消费者有变动会触发再均衡。那么是不是可以回归到别的消息队列的方式:不需要群组消费者也可以自己订阅主题?
kafka也提供了这样的案例,因为kafka的主题有分区的概念,那么如果没有群组就意味着你的自己订阅到特定的一个分区才能消费内容。如果是这样的话,就不需要订阅主题,而是为自己分配分区。一个消费者可以订阅主题(并加入消费者群组),或者为自己分配分区,但不能同时做这两件事情。注:group.id配置不能与其他consumer重复,否则会报错,直接去掉也行。
- package com.example.demo.consumer;
- import org.apache.kafka.clients.consumer.ConsumerRecord;
- import org.apache.kafka.clients.consumer.ConsumerRecords;
- import org.apache.kafka.clients.consumer.KafkaConsumer;
- import org.apache.kafka.common.PartitionInfo;
- import org.apache.kafka.common.TopicPartition;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
- import java.util.Properties;
- /**
- * @author 王柱星
- * @version 1.0
- * @title
- * @time 2018年12月11日
- * @since 1.0
- */
- public class PartitionConsumer {
- private static Properties getProps(){
- Properties props = new Properties();
- props.put("bootstrap.servers", "47.52.199.51:9092");
- props.put("session.timeout.ms", 30000); // 如果其超时,将会可能触发rebalance并认为已经死去,重新选举Leader
- props.put("enable.auto.commit", "false"); // 开启自动提交
- props.put("auto.commit.interval.ms", "1000"); // 自动提交时间
- props.put("auto.offset.reset","earliest"); // 从最早的offset开始拉取,latest:从最近的offset开始消费
- props.put("client.id", "consumer-3"); // 发送端id,便于统计
- props.put("max.poll.records","200"); // 每次批量拉取条数
- props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
- return props;
- }
- public static void main(String[] args) {
- try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(getProps())) {
- List<PartitionInfo> partitionInfoList = consumer.partitionsFor("test-syn");
- List<TopicPartition> topicPartitionList = new ArrayList<>();
- if(partitionInfoList != null){
- for(PartitionInfo partitionInfo : partitionInfoList){
- topicPartitionList.add(new TopicPartition(partitionInfo.topic(),partitionInfo.partition()));
- consumer.assign(topicPartitionList);
- }
- }
- Map map = consumer.metrics();
- System.out.println(map);
- for(;;){
- // 拉取任务超时时间
- ConsumerRecords<String,String> records = consumer.poll(1000);
- for(ConsumerRecord consumerRecord : records){
- System.out.println("partition:"+consumerRecord.partition());
- System.out.println("offset:"+consumerRecord.offset());
- System.out.println("key:"+consumerRecord.key());
- System.out.println("value:"+consumerRecord.value());
- }
- consumer.commitSync();
- }
- }
- }
- }
注:
- consumer.partitionsFor(“主题”)方法允许我们获取某个主题的分区信息。
- 知道想消费的分区后使用assign()手动为该消费者分配分区。
kafka系列五、kafka常用java API的更多相关文章
- Apache Kafka系列(五) Kafka Connect及FileConnector示例
Apache Kafka系列(一) 起步 Apache Kafka系列(二) 命令行工具(CLI) Apache Kafka系列(三) Java API使用 Apache Kafka系列(四) 多线程 ...
- 算法竞赛中的常用JAVA API :大数类(转载)
5.算法竞赛中的常用JAVA API :大数类 摘要 java中的基础数据类型能存储的最大的二进制数是 2 ^ 63 - 1 对应的十进制数是9223372036854775807(long类型的最大 ...
- Hadoop 系列(三)Java API
Hadoop 系列(三)Java API <dependency> <groupId>org.apache.hadoop</groupId> <artifac ...
- 常用Java API之Ramdom--用代码模拟猜数小游戏
常用Java API之Ramdom Ramdom类用来生成随机数字.使用起来也是三个步骤: 1.导包 import java.util.Random; 2.创建 Random r = new Rand ...
- 常用Java API之Scanner:功能与使用方法
Scanner 常用Java API之Scanner:功能与使用方法 Scanner类的功能:可以实现键盘输入数据到程序当中. 引用类型的一般使用步骤:(Scanner是引用类型的) 1.导包 imp ...
- 算法竞赛中的常用JAVA API:PriorityQueue(优先队列)(转载)
算法竞赛中的常用JAVA API:PriorityQueue(优先队列) PriorityQueue 翻译过来就是优先队列,本质是一个堆, 默认情况下堆顶每次都保留最小值,每插入一个元素,仍动态维护堆 ...
- 算法竞赛中的常用JAVA API :HashSet 和 TreeSet(转载)
算法竞赛中的常用JAVA API :HashSet 和 TreeSet set set容器的特点是不包含重复元素,也就是说自动去重. HashSet HashSet基于哈希表实现,无序. add(E ...
- 算法竞赛中的常用JAVA API :HashMap 和 TreeMap(转载)
算法竞赛中的常用JAVA API :HashMap 和 TreeMap 摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实 ...
- 8.算法竞赛中的常用JAVA API :Calendar日期类
8.算法竞赛中的常用JAVA API :Calendar日期类 摘要 在蓝桥杯中有关于日期计算的问题,正好java中的Date类和Calendar类提供了对日期处理的一些方法.Date类大部分方法已经 ...
- 7.算法竞赛中的常用JAVA API :String 、StringBuilder、StringBuffer常用方法和区别(转载)
7.算法竞赛中的常用JAVA API :String .StringBuilder.StringBuffer常用方法和区别 摘要 本文将介绍String.StringBuilder类的常用方法. 在j ...
随机推荐
- luogu1965 转圈游戏 (快速幂)
求(m*10^k+x)%n即可 #include<cstdio> #include<cstring> #include<algorithm> #define LL ...
- 【bzoj1568】 JSOI2008—Blue Mary开公司
http://www.lydsy.com/JudgeOnline/problem.php?id=1568 (题目链接) 题意 在线维护若干条直线,询问一些横坐标上的最高直线的纵坐标. Solution ...
- intest
/* ============================================================================ Name : http.c Author ...
- CF986C AND Graph
半年前做的一道题现在还是不会 x&y=0 意味着,x的补集的子集都是和x直接相连的 不妨令图中的点数就是2^n 那么可以直接从x^((1<<n)-1)开始记忆化爆搜,路上遇到的都是 ...
- 【codevs1004】四子连棋 状压bfs
题目大意:给定一个大小为 4*4 的棋盘,分别有 7 个黑子.7 个白子和 2 个空位构成,求出至少需要移动多少步,才能使得四个相同的棋子共线. 题解:显然每一种棋盘的局面都是一个状态,因此需要采用状 ...
- 淘宝助理导出的csv文件使用的是什么编码,您猜?
今天下午用Java读取从淘宝助理 V4.3 Beta1导出的csv文件,出现中文乱码情况. 一看就是文件编码引起的,不清楚淘宝助理导出的csv文件使用了什么编码,到百度搜索了一下,看到一些相关文章,但 ...
- LINUX_正则表达式
『正规表示法与通配符是完全不一样的东西!』这很重要喔!因为『通配符 (wildcard) 代表癿是 bash 操作接口癿一个功能』,但正觃表示法则是一种字符串处理癿表示方式 . (小数点):代表『 ...
- 20145215《网络对抗》Exp7 网络欺诈技术防范
20145215<网络对抗>Exp7 网络欺诈技术防范 基础问题回答 通常在什么场景下容易受到DNS spoof攻击? 在同一局域网下比较容易受到DNS spoof攻击,攻击者可以冒充域名 ...
- 【tools】vim删除命令
x 删除当前光标下的字符dw 删除光标之后的单词剩余部分.d$ 删除光标之后的该行剩余部分.dd 删除当前行. c 功能和d相同,区别在于完成删除操作后进入INSERT MODEcc 也是删除当前行, ...
- HDU3613 Manacher//EXKMP//KMP
http://acm.hdu.edu.cn/showproblem.php?pid=3613 每个字符都有一个权值,将一个字符串分成两半,如果某一半是回文串就把所有的字符权值加起来,否则当0来处理,问 ...