Java Program: Write a program to check given strings are Anagrams or not. 1. The Core Logic: "Sort and Compare." The fundamental idea behind this approach is that if two strings are anagrams, they must contain the exact same characters with the exact same frequencies. By sorting the characters of both strings alphabetically, any differences in the original "arrangement" are removed. If the sorted results are identical, the strings are anagrams. 2. Step-by-Step Breakdown s1.toCharArray(): Strings in Java are immutable objects. To manipulate or sort the individual characters, we first convert the string into a primitive char[] array. "listen" becomes ['l', 'i', 's', 't', 'e', 'n'] Arrays.sort(char1): This method uses a Dual-Pivot Quicksort algorithm. It rearranges the characters in the array into ascending order based on their Unicode values. ['l', 'i', 's', 't', 'e', 'n'] becomes ['e', 'i', 'l', 'n', 's', 't'] ['s', 'i', 'l', 'e', 'n', 't'] also becomes ['e', 'i', 'l', 'n', 's', 't'] Arrays.equals(char1, char2): This is a utility method that checks two things: Do the arrays have the same length? Does every element at index i in the first array match the element at index i in the second array? If both conditions are met, it returns true. 3. Missing Requirements for Production While this snippet works for the hardcoded values, a robust version of this code should include two additional checks: Length Check: Before sorting, you should check if s1.length() == s2.length(). If the lengths are different, they cannot be anagrams, and you can return false immediately without wasting time sorting. Imports: To make this code compile, you must import the java.util.Arrays utility at the top of your file: import java.util.Arrays;
Vinayak Titti’s Post
More Relevant Posts
-
Java Is Not As Simple As We Think. We’re taught that Java is predictable and straightforward. But does it always behave the way we expect? Here are 3 subtle behaviors that might surprise you. Q1: Which method gets called? You have a method overloaded with int and long. What happens when you pass a literal? public void print(int i) { System.out.println("int"); } public void print(long l) { System.out.println("long"); } print(10); It prints "int". But what if you comment out the int version? You might expect an error, but Java automatically "widens" the int to a long. However, if you change them to Integer and Long (objects), Java will not automatically widen them. The rules for primitives vs. objects are completely different. Q2: Is 0.1 + 0.2 really 0.3? In a financial application, you might try this: double a = 0.1; double b = 0.2; System.out.println(a + b == 0.3); // true or false? It prints false. In fact, it prints 0.30000000000000004. The Reason: Java (and most languages) uses IEEE 754 floating-point math, which cannot represent certain decimals precisely in binary. This is why for any precise calculation, BigDecimal is the only safe choice. Q3: Can a static variable "see" the future? Look at the order of initialization here: public class Mystery { public static int X = Y + 1; public static int Y = 10; public static void main(String[] args) { System.out.println(X); // 11 or 1? } } It prints 1. The Reason: Java initializes static variables in the order they appear. When X is calculated, Y hasn't been assigned 10 yet, so it uses its default value of 0. A simple reordering of lines changes your entire business logic. The takeaway: Java is not a simple language. Even professionals with years of experience get tripped up by its subtle behaviors and exceptions to the rules. The language rewards curiosity and continuous learning — no matter how senior you are. Keep revisiting the fundamentals. They have more depth than you remember. #Java #SoftwareEngineering #Coding #JVM #ProgrammingTips
To view or add a comment, sign in
-
🚀 Java Wrapper Classes: Hidden Behaviors That Trip Up Even Senior Developers Most developers know wrapper classes. Very few understand what happens under the hood — and that’s exactly where top companies separate candidates. Here’s a deep dive into the concepts that actually matter 1. Integer Caching Integer a = 4010; Integer b = 4010; System.out.println(a == b); // false Integer c = 127; Integer d = 127; System.out.println(c == d); // true Q.Why? Java caches Integer values in the range -128 to 127. Inside range → same object (cached) Outside range → new object (heap) 💡 Pro Insight: You can even extend this range using: -XX:AutoBoxCacheMax=<size> 2. == vs .equals() — Silent Bug Generator System.out.println(a == b); // false → reference comparison System.out.println(a.equals(b)); // true → value comparison Using == with wrapper objects is one of the most common production bugs. Rule: == → checks memory reference .equals() → checks actual value 3. hashCode() vs identityHashCode() System.out.println(a.hashCode()); System.out.println(System.identityHashCode(a)); Two objects can have: Same value → same hashCode() Different memory → different identityHashCode() 4. Silent Overflow in Primitive Conversion Integer a = 4010; byte k = a.byteValue(); // -86 What actually happens: byte range = -128 to 127 4010 % 256 = 170 170 interpreted as signed → -86 No error. No warning. This is how real-world bugs sneak into systems. 5. Powerful Utility Methods (Underrated) Integer.toBinaryString(4010); Integer.toHexString(4010); Integer.bitCount(4010); Integer.numberOfLeadingZeros(4010); Useful in: Bit manipulation Competitive programming Low-level optimization 6. Character & Boolean — Also Cached Boolean b1 = true; Boolean b2 = true; System.out.println(b1 == b2); // true Boolean → fully cached Character → cached in ASCII range 7. Character Utilities = Clean Code Character.isLetter('a'); Character.isDigit('3'); Character.isWhitespace('\t'); Character.toUpperCase('a'); The Big Picture Wrapper classes are NOT just primitives with methods. They reveal how Java handles: Memory optimization Object identity Autoboxing behavior Performance trade-offs A big thanks to my mentors Syed Zabi Ulla, peers, and the amazing developer community Oracle for continuously pushing me to go beyond basics and truly understand concepts at a deeper level. #Java #JVM #CoreJava #CodingInterview #FAANG #SoftwareEngineering #BackendDevelopment #ProgrammingTips
To view or add a comment, sign in
-
-
🚨 Java Records: Core Mechanics Most Developers Miss After understanding why records exist, the next step is more important: How do records actually behave under the hood? Because this is where most misconceptions start. 🧠 First: Records are NOT just “shorter classes.” They are a language-level construct with strict rules. When you write: public record User(Long id, String name) {} Java doesn’t “reduce boilerplate”… 👉 It generates a fully-defined, immutable data structure 🔍 What the compiler actually creates Behind the scenes, this becomes: private final fields A canonical constructor (all fields required) Accessor methods equals(), hashCode(), toString() Everything is tied to the data itself, not object identity. ⚠️ Common mistake: “Records don’t have getters.” Not true. They DO have accessors — just not JavaBean style. Instead of: getId() You get: id() 👉 This follows a different philosophy: “State is the API” 🔒 Immutability is enforced — not optional In a record: Fields are always final No setters allowed Object must be fully initialized There is no way to create a “half-filled” object. 🚫 No default constructor (and that’s intentional) Unlike normal classes: ❌ No no-arg constructor ✅ Only canonical constructor (all fields) This enforces: Every record instance is valid at creation time 🔥 Constructor behavior (important) You can customize construction — but with rules. Example: public record User(Long id, String name) { public User { if (id == null) { throw new IllegalArgumentException("id cannot be null"); } } } 👉 This is a compact constructor You can: ✔ Add validation ✔ Normalize data ✔ Add logic But you cannot: ❌ Skip field initialization ❌ Break immutability ⚖️ Records vs Lombok (under the hood mindset) Lombok → generates code you could have written Records → enforce rules you cannot bypass That’s a huge difference. 🧩 Subtle but critical behavior Records use: Value-based equality That means: new User(1L, "A").equals(new User(1L, "A")) // true 👉 Equality is based on data, not memory reference. 🧠 Why this matters in real systems Because records eliminate: Partial object states Hidden mutations Inconsistent equality logic They give you: ✔ Predictable behavior ✔ Safer concurrency ✔ Cleaner APIs 🚨 One key takeaway Records don’t just reduce code… They change how objects behave fundamentally If you still treat records like normal POJOs, You’ll miss the guarantees they provide. #Java #JavaRecords #BackendDevelopment #SpringBoot #SystemDesign #SoftwareEngineering #JavaDeveloper #CleanCode #Concurrency #Programming
To view or add a comment, sign in
-
...........🅾🅾🅿🆂 !!! 𝑷𝒍𝒂𝒕𝒇𝒐𝒓𝒎 卩卂尺 𝑺𝒊𝒎𝒓𝒂𝒏 𝙎𝙚 𝕄𝕦𝕝𝕒𝕜𝕒𝕥 🅷🆄🅸, but 🆁🅾🅱🆄🆂🆃 𝔸𝕣𝕦𝕟 nikla D͓̽i͓̽l͓̽ ka 🅳🆈🅽🅰🅼🅸🅲......!!!.............. Guys you must be wondering, what nonsense things am I writing...."kuch shaayar likhna hai toa kaahi aur likh, linkedin pe kiyu"??? But guess what.....the above phrase represents features of java: 🅾🅾🅿🆂:- 𝗢𝗯𝗷𝗲𝗰𝘁 𝗢𝗿𝗶𝗲𝗻𝘁𝗲𝗱 𝗣𝗿𝗼𝗴𝗿𝗮𝗺𝗺𝗶𝗻𝗴 ....'S' is just a connect letter...don't consider it... 𝑷𝒍𝒂𝒕𝒇𝒐𝒓𝒎:- 𝗣𝗹𝗮𝘁𝗳𝗼𝗿𝗺 𝗶𝗻𝗱𝗲𝗽𝗲𝗻𝗱𝗲𝗻𝘁.....java apps doesn't need to be recoded if you change the operating system😇😇😇 卩卂尺:- the word "par" sounds similiar to "por" and you can then call it 𝗣𝗼𝗿𝘁𝗮𝗯𝗹𝗲...Definitely platform independence makes java portable 𝑺𝒊𝒎𝒓𝒂𝒏:- Either you can say Simran sounds similiar to simple, hence 𝗦𝗶𝗺𝗽𝗹𝗲 is another feature....or say Simran is a very 𝗦𝗶𝗺𝗽𝗹𝗲 girl... 𝕄𝕦𝕝𝕒𝕜𝕒𝕥:- To say Mulakat, you need to say "Mul"...and at the end you are also using a "t"......guess it guess it.....yes it is 𝑴𝒖𝒍𝒕𝒊 𝑻𝒉𝒓𝒆𝒂𝒅𝒊𝒏𝒈....you will love smaller tasks in your programs into individual threads and then executing them concurrently to save your time.... 🅷🆄🅸:- doesn't "Hui" sound almost similiar to "high" I know there is a lot difference but say you are requiring same energy....just you can say "Hui" se 𝙃𝙞𝙜𝙝 𝙋𝙚𝙧𝙛𝙤𝙧𝙢𝙖𝙣𝙘𝙚.....ofcourse java gives a High level of performance as it is 𝑱𝒖𝒔𝒕 𝒊𝒏 𝒕𝒊𝒎𝒆 𝒄𝒐𝒎𝒑𝒊𝒍𝒆𝒅.... 🆁🅾🅱🆄🆂🆃:- Yes ofcourse java is 𝗥𝗼𝗯𝘂𝘀𝘁 because of its strong memory management..... 𝔸𝕣𝕦𝕟:- Arun contains "A" and "N".....Arun se 𝘼𝙧𝙘𝙝𝙞𝙩𝙚𝙘𝙩𝙪𝙧𝙖𝙡 𝙉𝙚𝙪𝙩𝙧𝙖𝙡....right??? Size of all data types in java is same for both 32 bit compiler as well as 64 bit compiler D͓̽i͓̽l͓̽ :- "Dil" had "DI" and "DI" se 𝗗𝗶𝘀𝘁𝗿𝗶𝗯𝘂𝘁𝗲𝗱...java Applications can be distributed and run at the same time on diff computers in same network 🅳🆈🅽🅰🅼🅸🅲:- Yes Java is also 𝗗𝘆𝗻𝗮𝗺𝗶𝗰 due to it's Dynamic class loading feature.... Just repeat the above phrase 2 to 3 times and you will be ablte to retain all the features of java untill you take your last breath.......100% guarantee....
To view or add a comment, sign in
-
🚀 Java Records in Spring Boot: Where They Actually Shine (and Where They Don’t) You’ve understood what records are. Now the real question is: Do you think you should use them in your backend APIs? Short answer: ✅ Yes — for most DTOs ❌ No — not everywhere Let’s break it down practically. 🧩 What are we talking about? Typical API request: POST /users { "name": "Tharun", "age": 26 } Traditional DTO: public class UserRequest { private String name; private int age; } With record: public record UserRequest(String name, int age) {} 🔥 Why Records are a great fit for APIs ✅ 1. Request data should be immutable A request is input, not a working object. With classes: request.setRole("ADMIN"); // accidental mutation With records: // impossible — no setters 👉 This enforces correctness by design. ✅ 2. Works seamlessly with Spring Boot Modern Spring Boot (2.6+ / 3.x): ✔ Supports records out of the box ✔ Uses Jackson to bind JSON → constructor @PostMapping public void createUser(@RequestBody UserRequest request) { System.out.println(request.name()); } 👉 No extra configuration needed. ✅ 3. Validation becomes cleaner public record UserRequest( @NotBlank String name, @Min(18) int age ) {} @PostMapping public void create(@Valid @RequestBody UserRequest request) {} 👉 Validation + immutability = safer APIs ✅ 4. Perfect for response DTOs public record UserResponse(String name, int age) {} 👉 Clear, predictable, no hidden state ⚠️ Where Records can hurt you This is where most devs misuse them 👇 ❌ 1. PATCH / partial updates { "name": "Tharun" } Problem: Missing fields → null Cannot distinguish: not sent explicitly null 👉 Records are too rigid here. ❌ 2. Mutable workflows If you need: dto.setName("A"); dto.setAge(25); 👉 Records cannot support step-by-step construction. ❌ 3. Complex transformations public void normalize() { this.name = name.trim().toLowerCase(); } 👉 Not possible — no mutation allowed. ❌ 4. JPA Entities (very important) @Entity public record User(...) {} // ❌ breaks Hibernate Why? No no-arg constructor No setters No proxy support 👉 Always use classes for entities. 🧠 Practical decision rule ✅ Use Records for: Request DTOs (simple POST/PUT) Response DTOs JPA projections Read-only data ❌ Use Classes for: Entities PATCH APIs Complex request flows Framework-heavy scenarios 💡 Advanced insight Records work best when your API follows: “Request = complete data snapshot” They struggle when your API needs: “Incremental/partial updates” 🚀 Final takeaway Records are the modern default for API DTOs But not a universal replacement for all classes If you use them correctly, you get: ✔ Cleaner code ✔ Safer APIs ✔ Fewer bugs ✔ Better readability Use them blindly, and you’ll hit limitations fast. #Java #JavaRecords #SpringBoot #BackendDevelopment #APIDesign #SystemDesign #SoftwareEngineering #JavaDeveloper #CleanCode #Programming
To view or add a comment, sign in
-
In Java, the transient keyword is a variable modifier used to exclude specific fields of an object from the serialization process. When an object is serialized (converted into a byte stream for storage or network transmission), any field marked as transient is ignored and not saved. Key Characteristics Purpose: It prevents sensitive or unnecessary data from being persisted. Deserialization Behavior: When the object is recreated (deserialized), transient fields are initialized with their default values (e.g., null for objects, 0 for integers, false for booleans) rather than their original values. Scope: It can only be applied to instance variables (fields). It cannot be used with methods, classes, or local variables. Common Use Cases Security: To protect sensitive information like passwords, PINs, or encryption keys that should not be stored in a file or sent over a network. Derived Data: For fields whose values can be easily recalculated from other data in the class (e.g., a fullName field derived from firstName and lastName). Non-Serializable Objects: To exclude fields that reference objects that do not implement the Serializable interface (e.g., database connections or file streams), which would otherwise cause a NotSerializableException. Performance: To reduce the size of the serialized byte stream by skipping temporary or large cache data. Behavior with Other Keywords static: Using transient with static is redundant. Static variables belong to the class, not the instance, and are naturally ignored by the default serialization process. final: The effect varies. If a final variable is initialized with a constant expression at declaration, the JVM may still serialize it despite the transient keyword. However, if it is initialized in a constructor, it will typically be treated as transient and reset to its default value upon deserialization. Related Annotations In modern Java frameworks, you may encounter similar functionality via annotations: @Transient (JPA/Hibernate): Tells the persistence provider not to store a field in the database. @JsonIgnore (Jackson): Prevents a field from being included when converting an object to JSON format.
To view or add a comment, sign in
-
✨ Most Useful Keywords In Java✨ ➡️final : The final keyword can be applied to classes, variables, methods, and blocks. Once assigned, it cannot be changed. A final class cannot be extended, a final variable cannot be reassigned, and a final method cannot be overridden. ➡️static : The static keyword can be applied to variables, methods, and blocks. Static members can be accessed using the class name without creating an object. Static methods cannot be overridden. ➡️abstract : Used to create a class or method that is incomplete and must be implemented by sub-classes ➡️assert : Used for debugging to test assumptions during runtime ➡️boolean : Represents a logical data type with values true or false ➡️break : Terminates a loop or switch statement immediately ➡️byte : Data type to store 8-bit integer values ➡️case : Defines a branch in a switch statement ➡️catch : Handles exceptions raised in a try block ➡️char : Stores a single character ➡️class : Used to declare a class ➡️continue : Skips the current loop iteration and continues with the next one ➡️default : Executes when no case matches in switch Defines default methods in interfaces ➡️do : Used in a do-while loop (executes at least once) ➡️double : Stores 64-bit decimal numbers ➡️else : Executes when an if condition is false ➡️enum :Defines a fixed set of constants ➡️extends : Used by a subclass to inherit another class ➡️finally : Block that always executes, used for cleanup ➡️float : Stores 32-bit decimal values ➡️for : Used for loop execution with initialization, condition, and increment ➡️if : Executes code when a condition is true ➡️implements : Used by a class to implement an interface ➡️import : Allows access to classes defined in other packages ➡️instanceof : Checks whether an object belongs to a specific class ➡️int : Stores 32-bit integer values ➡️interface : Used to declare a contract that classes must follow ➡️long : Stores 64-bit integer values ➡️new : Creates an object or instance ➡️package : Groups related classes and interfaces ➡️return : Sends a value back from a method and exits it ➡️short : Stores 16-bit integer values ➡️static : Belongs to the class, not object ➡️super : Refers to parent class object or constructor ➡️switch : Selects execution paths based on an expression ➡️synchronized : Controls thread access to prevent data inconsistency ➡️this : Refers to the current object ➡️throw : Explicitly throws an exception ➡️throws : Declares exceptions that a method may pass upward ➡️transient : Prevents variable from being serialized ➡️try : Wraps code that may generate exceptions ➡️void : Indicates a method returns no value ➡️volatile : Ensures variable value is read from main memory, not cache ➡️while: Executes a loop while condition remains true ➡️var: var enables local variable type inference ➡️record: record is a special immutable class used to store data only #javafeatures #oops #opentowork #fresher #softwareengineer #hiring #javadeveloper
To view or add a comment, sign in
-
🚀 Java Records: Features You Can Use (and Limits You Must Respect) By now, it’s clear that records are not just “shorter classes.” But here’s where things get interesting: Records are powerful — but only within a strict boundary Understanding both sides is what separates basic usage from real engineering clarity. 🧩 What records CAN do (yes, they’re more capable than you think) 🔹 1. Generics — fully supported Records work seamlessly with generics: public record Response<T>(T data, String status) {} 👉 Perfect for API wrappers, responses, and reusable models. 🔹 2. Methods — behavior is allowed Records aren’t “dumb containers.” public record User(Long id, String name) { public String displayName() { return name.toUpperCase(); } } ✔ You can add logic ✔ You can derive values But the state itself remains immutable. 🔹 3. Static members & blocks public record User(Long id, String name) { public static final String TYPE = "USER"; static { System.out.println("Record loaded"); } } ✔ Works just like normal classes ❗ But static ≠ instance state 🔹 4. Nested records (very useful) public record Order(Long id, Item item) { public record Item(String name, double price) {} } 👉 Clean way to model structured data 👉 Great for DTO hierarchies 🔹 5. Composition (record inside record) public record Order(Long id, Money price) {} public record Money(String currency, double amount) {} 👉 This is how you build real-world models 👉 Encourages clean, modular design 🔹 6. Validation annotations (Spring-friendly) public record User( @NotNull Long id, @NotBlank String name ) {} ✔ Works with Spring Boot ✔ Works with Hibernate Validator 👉 Records integrate cleanly with modern frameworks. ⚠️ What records CANNOT do (this is where people get it wrong) ❌ No extra instance fields You cannot add a hidden state: private int age; // ❌ not allowed 👉 All states must be declared in the record header. ❌ Cannot extend classes Records implicitly extend: java.lang.Record So: public record User(...) extends BaseEntity {} // ❌ not allowed ❌ No mutability — ever No setters No field updates No state changes 👉 Immutability is enforced, not optional. 🧠 The real design principle Records are built on: Structural immutability + value-based identity Not: “Flexible object with data + behavior” 🔥 Why this matters Because records push you toward: Clear data modeling Explicit contracts Safer APIs Fewer hidden bugs They remove: ❌ Accidental state ❌ Implicit behavior ❌ Uncontrolled changes 🧩 Final mental model Think of records as: A restricted Java class optimized for data modeling — not behavior modeling 💡 Clean takeaway Records support generics, methods, static members, nested types, and validation — but within a strictly controlled, immutable structure. #Java #JavaRecords #BackendDevelopment #SpringBoot #SystemDesign #SoftwareEngineering #JavaDeveloper #CleanCode #Programming #APIDesign
To view or add a comment, sign in
-
⏳Day 32 – 1 Minute Java Clarity – Comparable vs Comparator** Both sort. But who controls the sorting logic? ⚡ 📌 Core Difference: Comparable = object sorts itself (natural order). Comparator = external class defines custom sort logic. 📌 Code Comparison: import java.util.*; // Comparable – natural order (by age) class Student implements Comparable<Student> { String name; int age; Student(String name, int age) { this.name = name; this.age = age; } public int compareTo(Student other) { return this.age - other.age; // sort by age ascending } public String toString() { return name + "(" + age + ")"; } } // Comparator – custom order (by name) class NameComparator implements Comparator<Student> { public int compare(Student a, Student b) { return a.name.compareTo(b.name); // sort by name } } public class SortingDemo { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("Charlie", 22), new Student("Alice", 20), new Student("Bob", 21) ); Collections.sort(students); // Comparable → by age System.out.println(students); // [Alice(20), Bob(21), Charlie(22)] students.sort(new NameComparator()); // Comparator → by name System.out.println(students); // [Alice(20), Bob(21), Charlie(22)] // Java 8 Lambda Comparator students.sort((a, b) -> b.age - a.age); // sort by age descending System.out.println(students); } } 📌 Head-to-Head Comparison: | Feature | Comparable | Comparator | |---|---|---| | Package | java.lang | java.util | | Method | compareTo() | compare() | | Sort logic location | Inside the class | Outside the class | | Multiple sort orders | ❌ One only | ✅ Multiple | | Modifies class | ✅ Yes | ❌ No | 💡 Real-time Example: 👨🎓 Student Leaderboard : Comparable → Default sort by marks (fixed rule) Comparator → Sort by name, age, or rank depending on view ⚠️ Interview Trap: Can you use both Comparable and Comparator together? 👉 Yes! Comparable sets the default order. 👉 Comparator overrides it when passed explicitly. 📌 Pro Tip: // Java 8 Comparator chaining: students.sort( Comparator.comparing((Student s) -> s.age) .thenComparing(s -> s.name) ); // sort by age, then by name ✅ 💡 Quick Summary: ✔ Comparable → natural sort, modifies the class ✔ Comparator → custom sort, external, flexible ✔ Comparable uses compareTo(), Comparator uses compare() ✔ Use Comparator when you can't modify the class ✔ Java 8+ → prefer lambda Comparators ✅ 🔹 Next Topic → Java 8 Streams Introduction Did you know you can chain multiple Comparators in Java 8 with thenComparing()? Drop 🔥 if this was new to you! #Java #Comparable #Comparator #Sorting #JavaCollections #CoreJava #1MinuteJavaClarity #JavaDeveloper #100DaysOfCode
To view or add a comment, sign in
-
-
💬✨ STRING.INDENT() AND TRANSFORM(): SMALL JAVA APIS, BIGGER CLEAN CODE 🔸 TLDR Since Java 12, String.indent() and String.transform() make text processing much cleaner. Instead of manually splitting lines, looping, and rebuilding strings with StringBuilder, you can express the same idea in one fluent and readable pipeline. ☕✨ 🔸 WHY THIS MATTERS A lot of Java codebases still contain old-school string manipulation logic that feels heavier than the real intent. When your goal is simply: ▪️ indent some text ▪️ trim it ▪️ reformat it ▪️ chain a few transformations …you do not need ceremony anymore. Java already gives you elegant tools for that. ✅ 🔸 THE OLD WAY String[] lines = text.split("\n"); StringBuilder sb = new StringBuilder(); for (String line : lines) { sb.append(" ").append(line) .append("\n"); } String indented = sb.toString(); This works. But it is verbose, mechanical, and hides the real intention behind implementation details. 😅 🔸 THE MODERN WAY String indented = text.indent(4); String result = text .transform(String::strip) .transform(s -> s.replace(" ", "-")); Now the code says exactly what it does: ▪️ indent the text ▪️ strip extra outer spaces ▪️ replace spaces with dashes That is much easier to read at a glance. 👀 🔸 WHY THE MODERN WAY WINS ▪️ BUILT-IN Indentation is a common need, and indent() turns it into a direct API call. ▪️ CHAINABLE transform() lets you build a fluent pipeline instead of scattering temporary variables everywhere. ▪️ CLEANER INTENT The reader sees the purpose immediately, not the plumbing. ▪️ LESS BOILERPLATE No manual line splitting. No explicit loop. No StringBuilder dance. ▪️ BETTER TEACHING VALUE This is the kind of API that helps newer developers write code that looks modern and expressive from day one. 🔸 HOW IT WORKS ▪️ indent(n) adds indentation to each line of the string ▪️ transform(fn) applies a function to the string and returns the result ▪️ together, they help create readable string-processing pipelines 🔸 WHEN TO USE IT Use these APIs when: ▪️ formatting multiline text ▪️ preparing console output ▪️ adjusting generated content ▪️ applying several string operations in sequence ▪️ improving readability of utility code 🔸 TAKEAWAYS ▪️ String.indent() and String.transform() are available since Java 12 ▪️ they reduce boilerplate for common text operations ▪️ transform() is especially useful for fluent string pipelines ▪️ the biggest win is readability, not just fewer lines of code ▪️ small modern APIs can make everyday Java feel much cleaner #Java #Java12 #JDK #StringAPI #CleanCode #JavaDeveloper #SoftwareEngineering #Programming #BackendDevelopment #CodeQuality #DeveloperTips #ModernJava Go further with Java certification: Java👇 https://bit.ly/javaOCP Spring👇 https://bit.ly/2v7222 SpringBook👇 https://bit.ly/springtify JavaBook👇 https://bit.ly/jroadmap
To view or add a comment, sign in
-
More from this author
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development