While solving DSA problems recently, I encountered a small yet significant detail in Java that can lead to incorrect answers and silent bugs. I was comparing two strings like this: String s1 = new String("abbc"); String s2 = new String("abbc"); At first glance, it seems obvious that both strings are identical. However, when I checked: s1 == s2 // false This result surprised me. The reason is that in Java, the "==" operator does not compare the actual string values; it compares memory references. Even though both strings contain "abbc," they are two different objects created in memory. What actually works is: s1.equals(s2) // true The .equals() method compares the content inside the objects, which is typically what we want when working with Strings. This can become even more confusing with string literals: String a = "DSA"; String b = "DSA"; a == b // true In this case, Java uses the String Constant Pool, so both variables point to the same object. This can make == appear to work, but relying on it is risky and inconsistent. Key takeaways from this: - "==" checks reference equality, not value - .equals() checks actual string content - String Pool optimizations can hide bugs - One wrong operator can disrupt DSA logic, HashMaps, or real-world code DSA isn’t just about algorithms; it compels you to understand how the language behaves under the hood, truly. Have you ever lost time debugging something that came down to a single operator? #Java #DSA #Programming #SoftwareEngineering #JVM #CleanCode #CodingInterviews #BackendDevelopment #ProblemSolving
Java String Comparison Gotcha: '==' vs equals()
More Relevant Posts
-
🚀 Prefix Sum — Answer Range Queries in O(1) While practicing DSA, I revisited one of the simplest yet most powerful techniques — Prefix Sum. 👉 It helps compute range sums efficiently after one preprocessing pass. --- 💡 What is Prefix Sum? A prefix sum array stores the cumulative sum up to each index. Formula: prefix[i] = prefix[i-1] + arr[i] --- 📌 Example Input Array: arr = [2, 4, 6, 8, 10] Prefix Array becomes: prefix = [2, 6, 12, 20, 30] --- 🎯 Range Sum Query (L = 1, R = 3) Instead of looping every time: sum(L, R) = prefix[R] − prefix[L−1] = 20 − 2 = 18 ⚡ Preprocessing → O(n) ⚡ Each query → O(1) --- 🔥 Where is it useful? ✅ Range sum queries ✅ Subarray sum problems ✅ Count subarrays with given sum ✅ 2D prefix sum problems ✅ Competitive programming --- 💻 Java Implementation int[] prefix = new int[n]; prefix[0] = arr[0]; for(int i = 1; i < n; i++){ prefix[i] = prefix[i-1] + arr[i]; } // range sum from L to R int rangeSum = prefix[R] - (L > 0 ? prefix[L-1] : 0); --- ✨ Preprocess once, answer many queries fast! #DSA #PrefixSum #Coding #Java #CompetitiveProgramming #WomenInTech
To view or add a comment, sign in
-
-
📌 DSA Problem Series – Day 15 | Problem 2 | Array 🔹 Problem: Missing and Repeating Number 🧠 Problem Statement: You are given an array of size N containing numbers from 1 to N. One number is missing One number is repeating Your task is to find both numbers. ✅ Approach Used Use a HashMap to track frequency of elements Identify the repeating number when frequency > 1 Use mathematical sum formula to compute the missing number 💻 Java Solution class Solution { ArrayList<Integer> findTwoElement(int arr[]) { Map<Integer, Integer> map = new HashMap<>(); int n = arr.length; int expectedSum = n * (n + 1) / 2; int repeatingNumber = -1; int actualSum = 0; for (int item : arr) { if (map.containsKey(item)) { repeatingNumber = item; } map.put(item, map.getOrDefault(item, 0) + 1); actualSum += item; } int missingNumber = expectedSum - (actualSum - repeatingNumber); return new ArrayList<>(Arrays.asList(repeatingNumber, missingNumber)); } } ⏱️ Complexity Time Complexity: O(N) Space Complexity: O(N) 🎯 Key Takeaway Combining hashing with basic mathematics makes this problem simple and efficient. This pattern appears frequently in interviews and competitive programming. #DSA #Java #ProblemSolving #Arrays #CodingInterview #LeetCode #HashMap #Backend
To view or add a comment, sign in
-
-
🧠 “He tried to learn DSA using Java…” …and suddenly everything started timing out 😅 Same logic in C++? Runs smoothly. This literally happened to me recently. I was solving a DSA problem: ✔ Same algorithm ✔ Same complexity ✔ Same approach Java → TLE C++ → Works fine At first, it feels frustrating. But then you realize — there’s a deeper lesson here. 💡 Why does this happen? It’s NOT because Java is bad. It’s because performance is affected by language internals and runtime behavior, especially when problems are tight on limits. Some key reasons: 1️⃣ Input / Output speed Java’s default I/O is slow unless you explicitly optimize it. 2️⃣ Object overhead & Garbage Collection Java creates objects aggressively and has GC pauses. C++ gives more direct memory control. 3️⃣ Constant factors matter Even with the same O(N log N) complexity, Java can be noticeably slower due to: JVM abstraction Bounds checking Method call overhead ⚠️ Reality check: Java often needs ✅ Faster IO ✅ Iterative DFS instead of recursion ✅ Custom fast input classes ✅ Micro-optimizations Just to survive. Note: Java is sufficient for almost all DSA problems. In some tight cases, it just needs extra boilerplate like faster I/O or small optimizations. The core logic and algorithm still matter the most. #DSA #Java #Cpp #Programming #ProblemSolving #SoftwareEngineering #CodingLife #LearnToCode #TechCommunity
To view or add a comment, sign in
-
-
DSA with Java... Today I learnt about INTERPOLATION SEARCH.... Remember how binary search breaks the datasets into halves to reduce where to search for the target value? This is an improvement on it. It is best for uniformly distributed data. It guesses where the value might be in a calculated probe result. If the probe result is incorrect, we narrow the search and try again. The average case runtime is O(log(logn)) The worst case runtime is O(n) when the value increases exponentially. in what software engineering practices or features do we need to apply interpolation search instead? cheers 🥂 #dsa #java #softwareengineering #interpolationsearch
To view or add a comment, sign in
-
-
𝐃𝐚𝐲 𝟗 – 𝐑𝐞𝐯𝐢𝐬𝐢𝐭𝐢𝐧𝐠 𝟐-𝐃 𝐀𝐫𝐫𝐚𝐲𝐬 𝐢𝐧 𝐉𝐚𝐯𝐚 One important realization: 👉 In Java, a 2-D array is NOT actually a “matrix”. It is an array of arrays. That means: Each row is a separate array object. Rows can have different lengths. Memory is not necessarily continuous like in C/C++ Example: int[][] arr = new int[3][]; arr[0] = new int[2]; arr[1] = new int[4]; arr[2] = new int[3]; This is called a 𝑱𝒂𝒈𝒈𝒆𝒅 𝑨𝒓𝒓𝒂𝒚. Many beginners assume: arr.length == total elements ❌ But actually: arr.length → number of rows arr[i].length → number of columns in that specific row This small understanding prevents many traversal bugs. The deeper you understand memory structure, the cleaner your logic becomes. 🔹 Beginner Level 2-D Array Problems : These are simple but build strong fundamentals. 1️⃣ Print a 2D array----> Traverse and print all elements. 2️⃣ Find the sum of all elements 3️⃣ Row-wise sum-----> Print sum of each row separately. 4️⃣ Column-wise sum---->This helps understand traversal direction change. 5️⃣ Find the largest element----> Simple scanning problem. #Java #DataStructures #LearningInPublic #dailyChallenge
To view or add a comment, sign in
-
Built-in Method Overloading in Java 1️⃣ System.out.println() Overloaded to print different data types such as int, double, String, char, boolean, and Object. 2️⃣ Math class methods Methods like Math.max() and Math.min() are overloaded to work with int, long, float, and double values. 3️⃣ Other overloaded built-in methods Methods such as String.valueOf() and Arrays.sort() are overloaded to handle different data types and parameter combinations.
To view or add a comment, sign in
-
-
Learned something interesting about the char data type in Java today. I used to think char only stores characters. Turns out its numeric underneath. This small snippet made it obvious: char ch = 'A'; System.out.println(ch); // output: A System.out.println(ch + 1); // output: 66 'A' isn’t just a character, it has a numeric value (65). When Java performs arithmetic, it treats char as an integer. Tried this as well: char ch = '8'; System.out.println(ch); // output: 8 System.out.println((int) ch); // output: 56 That’s when ASCII / Unicode actually made sense instead of feeling like theory. Still learning the basics but understanding what’s happening underneath makes a big difference. #Java #LearningInPublic #Beginner #DSA
To view or add a comment, sign in
-
Rust Internals: Static Methods vs. Instance Methods and the "Self" Mystery Those migrating from C++ or Java to Rust often search in vain for the static keyword. In Rust, we organize logic using impl blocks, but the subtle differences in the signature determine whether we write idiomatic code or get entangled in ownership issues. Let's break down the mechanics behind Associated Functions, Methods, and the difference between Self and self. 1. Associated Functions (The "static" methods) An Associated Function is a function defined within an impl block that does not take an instance of the type as an argument. Context: It belongs to the type itself, not to a specific object. Best Practice: Conventionally used for constructors like new() or with_capacity(). Call: Via the type's namespace: User::new(). 2. Methods (The instance context) Methods are functions that use self (lowercase) as the first argument. This signals to the compiler that they operate on the data of a specific instance. &self: An immutable borrow. The method reads data without changing it. &mut self: A mutable borrow. Allows modification of the instance. self: Consumes the instance (move semantics). The object is "used up," which is often used in builder patterns or state transitions (state machines). 3. The Decisive Difference: Self vs. self This often causes confusion, yet the distinction is fundamental to the type system: Self (Uppercase: The Type Alias) Self is a reserved keyword that acts as an alias for the current type. In an impl MyLongStructName block, Self is simply an abbreviation for MyLongStructName. Advantage: It makes the code refactoring-friendly. If the name of the struct changes, only the impl line needs to be adjusted, not every return type within the block. self (Lowercase: The Value) self is the actual parameter name. It is syntactic sugar for the explicit type declaration: &self is equivalent to self: &Self &mut self is equivalent to self: &mut Self
To view or add a comment, sign in
-
-
Problem Statement: Write a function that reverses a string. The input string is given as an array of characters s. You must do this by modifying the input array in-place with O(1) extra memory. (LeetCode 344) Solution: So the approach I have applied in this problem is very very simple. We initialize a pointer start with 0 and another pointer end with ch.length-1, the start pointer points to first position of the array at the beginning and the end pointer points to the end of the array at the beginning . We swap the elements at start position with the element at end position and then we do start++ and end-- to move the start pointer to the next position and end pointer to the previous position (the second last position in the second iteration, third last in the third iteration and so on). We continue iteration until the condition (start <= end) fails. This simply reverse the array with character elements. Time Complexity : O(n) Space Complexity: O(1) Below is the Java Code for the following problem: public static void reverse(char []ch) { int start = 0; int end = ch.length-1; while(start <= end) { char temp = ch[start]; ch[start] = ch[end]; ch[end] = temp; start ++; end --; } }
To view or add a comment, sign in
-
Let’s have some fun : product(bool, DontCompileHugeMethods, true, \ "Do not compile methods > HugeMethodLimit") \ \ develop(intx, HugeMethodLimit, 8000, \ "Don't compile methods larger than this if " \ "+DontCompileHugeMethods") What is this 🧐 ? These are some compiler configurations from hotspot/share/compiler/compiler_globals.hpp. What do they stand for? They basically say that if your method has more than 8000 bytes of bytecode, it is no longer eligible for compiling. let’s try to get an approximation of how much 8000 bytes of bytecode is : As far as I know, each bytecode instruction ranges from 1 to 5 bytes in size (probably more in some cases). Let’s go with an average of 3 bytes per instruction: 8000/3 ~= 2666 bytecode instructions However, mapping Java instructions to bytecode instructions is hard and highly variable, but usually a Java instruction boils down to one or more bytecode instructions, let’s say 4 on average : 2666 bytecode instructions/4 = 666 instructions ”line” of Java code. Which means if you write more than 666 lines of code in your hot methods, they will rot in the interpreter 😹 , which is sloooooowwww as hell, and they will never get the honor of meeting the JIT. So don't write 666 lines methods 😂 Safe harbor: This is just a playground, don’t take these computations for granted! #HotspotVM
To view or add a comment, sign in
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