ক্যারেক্টার সেট (Character Set)

Posted on by

Categories:         

ক্যারেক্টার সেট

ক্যারেক্টার সেট নিয়ে কথা বলার আগে একটু এর পেছনের ইতিহাস জেনে নেওয়া উচিৎ। 

টেলিগ্রাফ

একটা সময়ে আমাদের যোগাযোগের একমাত্র মাধ্যম ছিল টেলিগ্রাফ। এতে করে তারের মাধ্যমে বৈদ্যুতিক সিগন্যাল পাঠানো হতো যা প্রায় ১৫০ বছর ধরে ব্যবহার করা হয়। স্যার চার্লস হুইটস্টোন (Sir Charles Wheatstone) এবং স্যার উইলিয়াম ফদারগ্রিল কুক (Sir William Fothergril Cooke) ১৮৩৭ সালে ইংল্যান্ডে সর্ব প্রথম রেলওয়ে টেলিগ্রাফ প্রবর্তন করেন যা কুক ও হুইটস্টোন টেলিগ্রাফ নামে পরিচিত। এতে কতগুলো চুম্বকশলাকা ব্যবহার করা হতো যেগুলোকে তড়িৎচুম্বকীয় আবেশের মাধ্যমে ঘড়ির কাঁটার দিকে (Clockwise) বা ঘড়ির কাঁটার বিপরীত দিকে (Anti-Clockwise) ঘোরানো যেত। চুম্বকশলাকা কোন দিকে ঘুরবে তা নির্ভর করতো টেলিগ্রাফের তারে বিদ্যুত কোন দিকে প্রবাহ হচ্ছে তার উপর। এতে সিগন্যাল ট্রান্সমিশনের যতগুলো চুম্বকশলাকা থাকত ঠিক ততগুলো তারের প্রয়োজন হতো। চুম্বকশলাকাগুলো একটি ডায়মন্ড আকৃতির গ্রিডের ওপরে বসানো থাকতো। এক বা একাধিক চুম্বকশলাকাকে আবিষ্ট করা হতো, তখন চুম্বকশলাকাগুলো গ্রিডের ভেতর একটি বর্ণ নির্দেশ করতো।

ঠিক একই বছর স্যামুয়েল মোর্স (Samuel Morse) আমেরিকান টেলিগ্রাফ প্রবর্তন করেন যা অনেক ক্ষেত্রেই কোক ও হুটিস্টোন টেলিগ্রাফ থেকে সহজ। এতে সিগনাল ট্রান্সমিশনের জন্য একটি তার ব্যবহার করার প্রয়োজন হতো এবং কোনো টেক্সট ইনফরমেশন কতগুলো অন অফ টোন বা লাইট বা ক্লিকের মাধ্যমে পাঠানো হতো যা একজন দক্ষ ব্যক্তি সহজেই বুঝতে পারতো কোনো রকম আদালা যন্ত্র ছাড়াই। একে মোর্সকোড (Morse Code) বলা হয়।

মোর্স কোড মূলত কতগুলো অন (On)/অফ (Off) এর ধারা এবং এগুলো বিভিন্ন দৈর্ঘ্যের হয়। সাধারণত অন সিগন্যালের দৈর্ঘ্য বড় হয় এবং একে ড্যাশ (-) দিয়ে উপাস্থাপন করা হয়। এর উচ্চারণ ডাহ (dah)। অফ সিগন্যালের দৈর্ঘ্য তুলনামূলক ভাবে একটু ছোট হয় একে ডট (.) দিয়ে উপস্থাপন করা হয় এবং এর উচ্চারণ ডিট (dit)। কতগুলো ডট এবং ড্যাশের সিকোয়েন্স দিয়ে একেকটি বর্ণকে উপস্থাপন করা হতো। একটি বর্ণে কতগুলো ড্যাশ এবং ডট থাকবে তার একটি চার্ট তৈরি করা হয়।

চিত্র : মোর্স কোড এর চার্ট

মোর্স কোড একটি বিশেষ আবিস্কার। এই পদ্ধতিতে ভুল হওয়ার সম্ভাবনা কম। এর কারণ খুব সহজে ভোল্টেজ আছে বা নেই, অন কিংবা অফ বলা যায় এবং অন্যান্য টেলিগ্রাফিক পদ্ধতির চেয়ে সহজ। ঠিক এই কারণেই আধুনিক কম্পিউটারগুলোতে বাইনারি সংখ্যা ব্যবহার করা হয়। ১৮৪৪ সালের ২৪ মে মোর্স সর্বপ্রথম একটি ইউ এস টেলিগ্রাফিক লিংকে মোর্স কোড ব্যবহার করে বার্তা পাঠান যা ছিল, What hath God wrought।

সুতরাং দেখা যাচ্ছে একটি টেক্সট তথ্যকে প্রথমে মোর্স কোড অর্থাৎ ডট-ড্যাশ রূপান্তরিত করা হয়, তারপর এটি তারের মাধ্যমে পাঠানো হয়, যেখানে থেকে আবার সেই ডট-ড্যাশ থেকে টেক্সটে রূপান্তরিত করা হয়।

এই তথ্য থেকে দেখা গেল যে, টেলিগ্রাফিক কমিউনিকেশনে মূলত কতগুলো সংকেত (মোর্স কোডের ক্ষেত্রে ডট-ড্যাশ) পাঠানো হয়, সেগুলো পরবর্তীতে অনুবাদ করে মূল তথ্যটি পুনরুদ্ধার করা হয়।

চিত্র : কোক ও হুইটস্টোন টেলিগ্রাফ

এবার আমরা একটু সামনে এগিয়ে করে মূল আলোচনায় চলে আসবো।

মূল ব্যাপার হচ্ছে, ক্যারেক্টার বা বর্ণ হলো যেকোনো লিখন পদ্ধতির মৌলিক একক। এদেরকে একটি বিশেষ আকৃতি বা ছবি দিয়ে প্রকাশ করা হয়। ইংরেজিতে এদের বলে glyph। তবে কম্পিউটার বর্ণ কিংবা ছবি এইরকম কোনো কিছুই মেমোরিতে স্টোর করতে পারে না। কম্পিউটার যা স্টোর করতে পারে তা হলো বিট (bit) যার অর্থ হতে পারে, yes অথবা no; true অথবা false; 1 অথবা 0। কম্পিউটার যেহেতু বিদ্যুতে চলে, সুতরাং আসলে বিট হলো একটি বৈদ্যুতিক পাল্স যা কখনো থাকে, কখনো থাকে না। আমাদের বোঝার সুবিধার্থে এগুলো 0 এবং 1 দিয়ে প্রকাশ করা হয়। তাহলে আমরা সহজ করে বলতে পারি যে, কম্পিউটার যা কিছু স্টোর বা কোনো কমিউনিকেশন লিংক দিয়ে ট্রান্সফার করে তা হলো কতগুলো বিট বা বাইনারি সংখ্যার সিকোয়েন্স বা ধারা।

এখন কতগুলো বাইনারি সিকোয়েন্সকে কোনো ক্যারেক্টার বা বর্ণতে প্রকাশ করতে হলে আমাদের কতগুলো নিয়মকানুনের দরকার হয়। এই নিয়মকানুনগুলোকে এনকোডিং স্কিম (Encoding Scheme) বলা হয়। যেমন,

চিত্র ১.৩৪: ASCII Encoding of ‘java’

উপরের ছবিতে, java শব্দটিকে বাইনারি সিকোয়েন্সে রূপান্তরিত করা হয়েছে। এখানে ‘a’ এর বাইনারি হচ্ছে 01100001, ‘b’ এর বাইনারি 01100010, এভাবে ‘c’ এর বাইনারি 01100011। এভাবে ইংরেজি বর্ণমালার ২৬ টি বর্ণকে বাইনারিতে রূপান্তরিত করা হলে,

a -> 01100001

b -> 01100010

c -> 01100011

d -> 01100100

e -> 01100101

f -> 01100110

g -> 01100111

h -> 01101000

i -> 01101001

j -> 01101010

k -> 01101011

l -> 01101100

m -> 01101101

n -> 01101110

o -> 01101111

p -> 01110000

q -> 01110001

r -> 01110010

s -> 01110011

t -> 01110100

u -> 01110101

v -> 01110110

w -> 01110111

x -> 01111000

y -> 01111001

z -> 01111010

চিত্র: ইংরেজি বর্ণমালার ASCII Encoding

এখন যদি আমরা এই ২৬ টি বর্ণের বাইনারি ভ্যালু মনে রাখতে পারি, তাহলে খুব সহজেই বাইনারিতে যেকোনো লেখা পড়তে পারব, তাই নয় কি?

* এখন একটি প্রোগ্রাম লিখে ফেলুন যা একটি ক্যারেক্টার ইনপুট নেবে এবং সেটি যদি একটি আসকি ক্যারেক্টার হয়, তাহলে তা বাইনারিতে রূপান্তরিত করে কনসোলে প্রিন্ট করবে। 

উপরে যে পদ্ধতিতে ইংরেজি ভাষার বর্ণগুলোকে বাইনারিতে রূপান্তরিত করা হয়েছে, তাকে বলা হয় আসকি (ASCII)। এর পূর্ণরূপ হচ্ছে আমেরিকান স্ট্যান্ডার্ড কোড ফর ইনফরমেশন এক্সচেঞ্জ (American Standard Code for Information Interchange)। এই পদ্ধতিতে 0-0, ছোটো হাতের অক্ষর (a-z), বড় হাতের অক্ষর (A-Z), মুষ্টিমেয় যতিচিহ্ণ যেমন, ডলার চিহ্ন ($), এমপারস্যান্ড চিহ্ন (&) ইত্যাদি এবং এছাড়াও আরও কতগুলো কন্ট্রোল কোড যেমন, ক্যারেজ রিটার্ন (Carriage Return), লাইনফিড (Line Feed) ইত্যাদি নিয়ে মোট 128 টি ক্যারেক্টারের একটি টেবিল তৈরি করা হয়। এটি আসকি টেবিল নামে পরিচিত। গুগলে ASCII Table লিখে সার্চ করলেই টেবিলটি চলে আসবে। এই টেবিলে 128 ক্যারেক্টার থাকার কারণ হচ্ছে, প্রথম যে টেবিলটি তৈরি করা হয়েছিল, সেটি ছিল 7 বিটের। আমরা জানি যে, 7 বিট দিয়ে সর্বোচ্চ 128 () টি কম্বিনেশন তৈরী করা যায়, সুতরাং এতে সর্বোচ্চ 128 টি ক্যারেক্টার থাকতে পারে। পরবর্তীতে এই টেবিলকে সম্প্রসারিত করে 8 বিটে উন্নীত করা হয় এবং এতে 256 () টি ক্যারেক্টার রয়েছে।

http://www.ascii-code.com/ এই লিংকটিতে গেলে 256 টি ক্যারেক্টারের তালিকা দেখা যাবে।

এখন প্রশ্ন হতে পারে তাহলে আমরা কম্পিউটার স্ক্রিনে যে লেখা দেখছি তা কীভাবে দেখছি। এর উত্তর জানতে হলে আমাদের জানতে হবে ফন্ট কী।

ফন্ট (Font)

ফন্ট হলো এক ধরনের কম্পিউটার কোড যার মাধ্যমে কোনো একটি বর্ণকে কম্পিউটার স্ক্রিনে Glyph বা pictograph এর মাধ্যমে প্রদর্শন বা উপস্থান করা হয়। অর্থাৎ, ফন্ট হচ্ছে কোনো ক্যারেক্টার বা বর্ণের ছবি। এর মধ্যে ক্যারেক্টারের ও Glyph এর ম্যাপিং থাকে। যখন একটি ক্যারেক্টার ডিসপ্লে করার দরকার হয়, আমরা জানি যে, প্রত্যেকটি ক্যারেক্টারের একটি স্বতন্ত্র সংখ্যা থাকে, সেই সংখ্যা দিয়ে ফন্ট থেকে একটি Glyph বা ছবি বের করে আনা হয়। সহজ কথায় বলতে গেলে, ফন্ট মূলত কতগুলো Glyph এর অ্যারে যার ইনডেক্স হলো ক্যারেক্টারের সংখ্যা। একটি ফন্টের ভেতর আরও একাধিক ডেটা থাকতে পারে, যেমন, কীভাবে একটি ফন্টকে regular, italic, bold, uppercase, lowercase রূপান্তরিত করা যায় ইত্যাদি। এছাড়াও kerning (দুটি ক্যারেক্টারের মধ্যের দূরত্ব), hinting (কীভাবে বিভিন্ন সাইজের ফন্ট ডিসপ্লে বা আঁকা যায়), ligatures (অনেক সময় একাধিক glyph দিয়ে একটি ক্যারেক্টার তৈরি করতে হয়, যেমন, যুক্তবর্ণ) ইত্যাদি তথ্যও থাকে।

এবার আরও ভেতরে প্রবেশ করার আগে কতগুলো টার্ম জেনে নেওয়া যাক,

এনকোড (Encode)/ এনকোডিং (Encoding), ক্যারেক্টার সেট (Character Set) / কারসেট (charset), কোড পয়েন্ট (Code Point)

কম্পিউটার শুধুমাত্র বাইনারি সংখ্যা নিয়ে কাজ করে। কম্পিউটারে আমরা যে বর্ণমালা ব্যবহার করি, সেগুলোর প্রত্যেকটিকে একটি ইন্টিজার সংখ্যা (অঋণাত্বক বা নন-নেগেটিভ) দিয়ে ম্যাপিং করা হয়। ম্যাপিংয়ের অর্থ হচ্ছে, কোনো একটি ক্যারেক্টার বা বর্ণ একটি নির্দিষ্ট সংখ্যাকে নির্দেশ করে। যে নির্দিষ্ট ক্যারেক্টার বা বর্ণগুলোর এই ম্যাপিং করা হয়, তাদেরকে ক্যারেক্টার সেট (Character Set) / কারসেট (charset) বলা হয়। প্রত্যেকটি ক্যারেক্টারের যে ইন্টিজার ভ্যালু বা মান দেওয়া হয়, তাকে কোড পয়েন্ট (Code Point) বলা হয়। এই পুরো প্রক্রিয়াকে এনকোডিং (Encoding) বলা হয়। উদাহরণ, Latin capital letter A (‘A’) এর ASCII টেবিলে ইন্টিজারের ভ্যালু 65। বাইনারিতে এটি হয়ে যায়, 01000001। এখানে Latin capital letter A হচ্ছে আসকি ক্যারেক্টার সেটের একটি এনকোডেড ক্যারেক্টার এবং এর কোড পয়েন্ট হচ্ছে 01000001।

এখানে মনে রাখতে হবে যে, একই ক্যারেক্টারের কোড পয়েন্ট বিভিন্ন এনকোডিং স্কিমে বিভিন্ন হতে পারে এবং একই কোড পয়েন্ট বিভিন্ন এনকোডিং স্কিমে বিভিন্ন হতে পারে।

স্ট্রিং (String)

একাধিক ক্যারেক্টার এক সঙ্গে থাকলে তাদেরকে স্ট্রিং বলা হয়।

বাইনারি (Binary), অকটাল (Octal), ডেসিমাল (Decimal), হেক্সাডেসিামাল (Hexadecimal) / হেক্স (Hex)

আমরা জানি যে, যেকোনো সংখ্যাকে অনেকগুলো উপায়ে লেখা যায়। যেমন, 125 একটি ডেসিমাল সংখ্যা। এর বাইনারি হচ্ছে, 01111101। একইভাবে এর অকটাল, 175 এবং হেক্স বা হেক্সাডেসিমাল হচ্ছে 7D। সবগুলোর ভ্যালু যদিও এক কিন্তু হেক্স দৈর্ঘ্যে একটু ছোট এবং বাইনারি থেকে বেশি সহজে পড়া যায়। তাই অনেক সময় দেখা যাবে একই মানের সংখ্যা কোথাও হেক্স, আবার কোথাও ডেসিমাল দিয়ে প্রকাশ করা হচ্ছে।

আসকি টেবিল থেকে 128টি ক্যারেক্টার পাওয়া যায়। বর্ধিত আসকি (Extended ASCII) টেবিল থেকে যদিও 256 টি ক্যারেক্টার পাওয়া যায়, কিন্তু তা শুধুমাত্র ইংরেজি বর্ণমালার জন্য সীমাবদ্ধ। পৃথিবীতে নানা রকম ভাষা আছে, বাংলা (Bangla), ফরাসী (French), সুইডিস (Swidish), জার্মান (German) ইত্যাদি। এগুলোর বর্ণ আলাদা। সুতরাং দেখা যাচ্ছে আসকি এনকোডিং স্কিম দিয়ে এই ভাষার লেখাগুলোর বর্ণ ব্যবহার করা যাচ্ছে না। এই সমস্যা সমাধান করার জন্য অনেকেই নানা রকম এনকোডিং স্কিম তৈরি করেছে, যেমন- ISO-646, ISO-8859, UCS-2, UCS-4 CP47, Windows-1250, MIK, ISCII, TSCII ইত্যাদি।

এছাড়াও পৃথিবীতে আরও অনেক ভাষা রয়েছে- যেমন হিন্দি, আরবি, কোরিয়ান, রাশিয়ান ইত্যাদি। চাইনিজ এবং জাপানিজ ভাষায় হাজার হাজার বর্ণ রয়েছে যা কিনা 8 বিট দিয়ে প্রকাশ করা সম্ভব নয়। এই সমস্যা সমাধান করার জণ্যে পরবর্তীতে মাল্টি-বাইট এনকোডিং স্কিম (Multi-Byte Encoding Scheme) প্রবর্তন করা হয়। 8 বিটের পরিবর্তে যদি 16 বিট ব্যবহার করা হয়, তাহলে বা 65536 টি কম্বিনেশন পাওয়া যায়। এরকম একটি এনকোডিং স্কিম হলো, BIG-5। এ পদ্ধতিতে একটি বাইনারি সিকোয়েন্সের ধারাকে 8 বিট অন্তর অন্তর না ভেঙে 16 বিট পর পর ভেঙে সেই ব্লকের ভ্যালু নিয়ে কোড পেজ (Code Page) বা ক্যারেক্টার সেট থেকে বের করা হয়। এটি মূলত বেসিক চাইনিজ বর্ণগুলোর জন্য ব্যবহার করা হয়। এছাড়াও আরেকটি এনকোডিং সিস্টেম হলো, GB18030 যাতে বেসিক এবং সিম্প্লিফায়ড দুটো বর্ণমালায় রয়েছে।

ইউনিকোড (Unicode)

সুতরাং দেখা যাচ্ছে যে, বিভিন্ন ভাষার বর্ণ কম্পিউটার সিস্টেমে ব্যবহার করার জন্য বিভিন্ন রকম এনকোডিং সিস্টেম তৈরি করা হয়ছে। এগুলো অনেক সময় একটি আরেকটির সঙ্গে কাজ করে না। একই সঙ্গে একাধিক ভাষার বর্ণ এক সঙ্গে ব্যবহার করা কঠিন হয়ে পরে। এইসব সমস্যা সমাধান করার জন্য অবশেষে একটি এনকোডিং স্ট্যান্ডার্ড প্রবর্তন করা হয়, যার মাধ্যমে সবগুলো ভাষার বর্ণগুলো ব্যবহার যায়। এই এনকোডিং স্ট্যান্ডার্ডকে ইউনিকোড (Unicode) বলা হয়। তবে এখানে একটি বিষয় মনে রাখতে হবে যে, ইউনিকোড কোনো এনকোডিং স্কিম নয়। ইউনিকোড মূলত একটি টেবিল যা কিনা ক্যারেক্টারগুলো কোড পয়েন্ট নির্দেশ করে। এগুলোকে এনকোডিং করার জন্য একাধিক এনকোডিং স্কিম রয়েছে। ইউনিকোড কোড পয়েন্ট হেক্সাডেসিম্যালে লেখা হয়। এর কারণ হেক্সাডেসিম্যাল সংখ্যাগুলো ছোট। প্রত্যেকটি কোড পয়েন্টের আগে “U+” থাকে। যেমন, বাংলা ‘ক’ এর কোড পয়েন্ট হচ্ছে, U+0995। ‘খ’ এর কোড পয়েন্ট হচ্ছে, U+0996

ইউনিকোড টেবিলে মোট 1,114,112 কোড পয়েন্ট রয়েছে যেখানে সব ধরনের চিহ্ন, ইউরোপিয় (European), মধ্যপ্রাচ্যীয় (Middle Eastern), দক্ষিনীয় (Southern), প্রাচ্যীয় (Eastern), উত্তরীয় (Northern), পশ্চিমা (Western), প্রাগৈতিহাসিক (Pre-Historian) সব ধরনের ক্যারেক্টার রয়েছে। এর ফলে একটি ডকুমেন্টে যেকোনো ধরনের ক্যারেক্টার ব্যবহার করা যায়।

1,114,112 টি সংখ্যা রাখার জন্য ইউটনিকোডে 4 বাইট বা 32 বিট ব্যবহার করা হয়। তবে এখানে সমস্যা হচ্ছে যে, চাইনিজ বা জাপানিজ ক্যারেক্টারগুলো এনকোড করা জন্য বড় সংখ্যা দরকার হলেও সবগুলো বর্ণের জন্য 32 বিট দরকার পড়ে না। যেমন, 

‘A’ বর্ণটি এনকোড করা হলে তা হবে 00000000 00000000 00000000 01000001

‘B’ বর্ণটি এনকোড করা হলে তা হবে – 00000000 00000000 00000000 01000010 

যা কিনা যা দরকার তার দেখে অনেক বেশি। তাই ইউনিকোড কোড পয়েন্ট এনকোডিং অপটিমাইজ করার জন্য কতগুলো বিশেষ এনকোডিং স্কিম তৈরি করা হয়েছে। যেমন, UTF-32, UTF-16, UTF-8। UTF-32 এনকোডিং স্কিমে সবগুলো কোড পয়েন্ট 32 বিটে এনকোড করা হয়। UTF-16, UTF-8 এর এনকোডিং স্কিম একটু ভিন্ন। যদি কোনো বর্ণ বা ক্যারেক্টার এক বাইট বা 8 বিটে প্রকাশ করা যায়, তাহলে সেটি এক বাইট বা 8 বিটে এনকোড করবে এবং এর স্কিম হবে UTF-8। যদি 2 বাইট দরকার হয় তাহলে এটি 2 বাইট ব্যবহার করবে এবং স্কিম হবে UTF-16। এভাবে 4 বাইট পর্যন্ত ব্যবহার করবে। এতে করে অনেক কম জায়গায় ব্যবহার করা যায়। অন্যদিকে UTF-16 মাঝামাঝি, যা কিনা 2 বাইট থেকে শুরু করে 4 বাইট পর্যন্ত ব্যবহার করতে পারে।

character

Encoding

Bits

A

UTF-8

01000001

A

UTF-16

00000000 01000001

A

UTF-32

00000000 00000000 00000000 01000001

টেবিল: ইউনিকোড কোড পয়েন্ট এনকোডিং স্কিম

তাহলে ইতিমধ্যে আমরা জেনে গেছি, ক্যারেক্টার সেট এবং এনকোডিং কী। ক্যারেক্টারকে কম্পিউটারে স্টোর করতে হয় কতগুলো সংখ্যার মাধ্যমে। এনকোডিং স্কিমের উপর ভিত্তি করে একটি ক্যারেক্টার বা বর্ণকে বিভিন্ন রকম সংখ্যা বা বিট সিকোয়েন্স দিয়ে এনকোড করা যায়। একটি সংখ্যা বা বিট সিকোয়েন্স বিভিন্ন বর্ণ বা ক্যারেক্টার প্রকাশ করতে পারে। আমরা এও বুঝতে পারলাম যে মোর্স কোড মূলত একটি এনকোডিং সিস্টেম যাতে বর্ণ বা ক্যারেক্টারগুলো বিট সিকোয়েন্স না হয়ে কতগুলো ডট-ড্যাশের সিকোয়েন্স।

এখন যদি কোনো বিট সিকোয়েন্স যদি আমরা স্টোর করি বা কোনো কমিউনিকেশন লিংকের মাধ্যমে ট্রান্সফার করি, তাহলে এনকোডিং স্কিম জানা থাকলে তা সহজে পাঠোদ্ধার করা সম্ভব।

Share on:

Author: A N M Bazlur Rahman

Java Champion | Software Engineer | JUG Leader | Book Author | InfoQ & Foojay.IO Editor | Jakarta EE Ambassadors| Helping Java Developers to improve their coding & collaboration skills so that they can meet great people & collaborate

100daysofcode 100daysofjava access advance-java agile algorithm arraylist article bangla-book becoming-expert biginteger book calculator checked checked-exceptions cloning code-readability code-review coding coding-convention collection-framework compact-strings completablefuture concatenation concurrency concurrentmodificationexception concurrentskiplistmap counting countingcollections critical-section daemon-thread data-race data-structure datetime day002 deliberate-practice deserialization design-pattern developers duration execute-around executors export fibonacci file file-copy fork/join-common-pool functional future-java-developers groupby hash-function hashmap history history-of-java how-java-performs-better how-java-works http-client image import inspiration io itext-pdf java java-10 java-11 java-17 java-8 java-9 java-developers java-performance java-programming java-thread java-thread-programming java11 java16 java8 lambda-expression learning learning-and-development linkedlist list local-type-inference localdatetime map methodology microservices nio non-blockingio null-pointer-exception object-cloning optional packaging parallel pass-by-reference pass-by-value pdf performance prime-number programming project-loom race-condition readable-code record refactoring review scheduler scrum serialization serversocket simple-calculator socket software-development softwarearchitecture softwareengineering sorting source-code stack string string-pool stringbuilder swing thread threads tutorial unchecked vector virtual-thread volatile why-java zoneid