Java String

What is String in Java?

Java String is a sequence of characters.

Java String variable contains a collection of characters surrounded by double quotes.

An array of characters works same as Java String.

Java Strings are used for storing text.

In Java, Strings are immutable or final or constant which means each time when we are creating or editing or performing any method to change string, one string created in "String Constant Pool"

Immutable strings eliminate race conditions in multi-threaded applications.

How to create a String in Java?

There are two ways to create a String object:

  1. By string literal
  2. By new keyword

1- String literal

String str1 = "Hello World!";
String str2 = "Hello World!";

Each time you create a string literal, the JVM checks the "string constant pool" first. If the string already exists in the pool, a reference to the pooled instance is returned. If the string doesn't exist in the pool, a new string instance is created and placed in the pool.

In other words, we don't create any String object using new keyword above. The JVM does that task for us, it create a String object. If the String object exist in the memory, it doesn't create a new String object rather it assigns the same old object to the new instance, that means even though we have two String instances above(str1 and str2) compiler only created one String object and assigned the same to both the instances.

For example there are 5 String instances that have same value, it means that in memory there is only one String object having the value and all the 5 String instances would be pointing to the same String object.

What if we want to have two different String object with the same String. For that we would need to create Strings using new keyword

2- Using new keyword

String str1 = new String("Hello World!");
String str2 = new String("Hello World!");

In such case, the JVM will create a new String object in normal (non-pool) heap memory.

Notice that JVM handles allocation of memory space for string variables efficiently, whenever we create a String variable and assign a String value with String Literal(double quotes) , JVM check value of String variable in String pool, if found, it returns reference of String object, if not found then it creates a new String object in String pool and return reference of it.

I found some images from google to represent. So, there are three images below.

Continue reading

Python Language Basics

🐍 Python Collection Data Types

⚖️ Quick Comparison Table

TypeOrderedMutableUniqueIndexableDuplicates AllowedNotable Use Case
listGeneral-purpose sequence
tupleFixed-size data
setUnique elements, set operations
frozensetImmutable set
dict✅ (keys)✅ (by key)✅ (values only)Key-value pairs
dequeLimited (0, -1)Fast double-ended queue
namedtuple✅, attr accessTuple with field names
defaultdict✅ (keys)✅ (by key)✅ (values only)Dict with auto-init for missing keys
Counter✅ (keys)✅ (by key)✅ (values count duplicates)Counting/frequency of elements

🔹 dict keys must be unique
🔹 Tuples can be used as dict keys if they’re hashtable (no lists inside)

Immutable Data Types Table

TypeDescriptionExample
intInteger numbersx = 10
floatFloating-point numbersx = 3.14
boolBoolean valuesx = True
strString (sequence of characters)x = "hello"
tupleImmutable ordered sequencex = (1, 2, 3)
frozensetImmutable setx = frozenset([1, 2, 3])
bytesImmutable byte sequencex = b'data'
complexComplex numbersx = 2 + 3j
NoneTypeRepresents 'no value'x = None

Collection Operations Time Complexity(BigO) Table

CollectionOperationTime ComplexityExample
listIndexingO(1)x = lst[2]
listAppendO(1) amortizedlst.append(10)
listInsert (start/middle)O(n)lst.insert(1, 99)
listPop (end)O(1)x = lst.pop()
listPop (start)O(n)x = lst.pop(0)
listRemove by valueO(n)lst.remove(10)
listMembership testO(n)if 5 in lst: pass
listIterationO(n)for x in lst: pass
listSortO(n log n)lst.sort()
listSlicingO(k)sub = lst[1:4]
tupleIndexingO(1)x = tpl[1]
tupleMembership testO(n)if 3 in tpl: pass
tupleIterationO(n)for x in tpl: pass
tupleConcatenationO(n + m)tpl3 = tpl1 + tpl2
tupleSlicingO(k)sub = tpl[1:3]
setAddO(1)s.add(5)
setRemoveO(1)s.remove(5)
setMembership testO(1)if 5 in s: pass
setIterationO(n)for x in s: pass
frozensetMembership testO(1)if 2 in fs: pass
frozensetIterationO(n)for x in fs: pass
dictGetO(1)x = d['key']
dictSetO(1)d['key'] = 10
dictDeleteO(1)del d['key']
dictMembership testO(1)if 'key' in d: pass
dictIterationO(n)for k, v in d.items(): pass

📦 1. list

  • ✅ Mutable
  • ✅ Ordered
  • ❌ Not Unique
  • ✅ Indexable
  • ✅ Duplicates allowed

Use case: Dynamic, ordered collections with duplicates.

my_list = [1, 2, 3, 4]
my_list.append(4)
my_list.insert(0, 0)
my_list[0] = 10

🔒 2. tuple

  • ❌ Immutable
  • ✅ Ordered
  • ❌ Not Unique
  • ✅ Indexable
  • ✅ Duplicates allowed

Use case: Fixed-size data, coordinates, function return values.

position = (10, 20)
# position[0] = 5  # ❌ Error

🧺 3. set

  • ✅ Mutable
  • ❌ Unordered
  • ✅ Unique
  • ❌ Indexable
  • ❌ Duplicates not allowed

Use case: Unordered collections with no duplicates, set operations.

unique_items = {1, 2, 3}
unique_items.add(4)
unique_items.discard(2)

🧭 4. dict

  • ✅ Mutable
  • ✅ Ordered (Python 3.7+)
  • ✅ Unique keys
  • ✅ Key-based access
  • ✅ Duplicates allowed for values

Use case: Fast key-value lookup, structured data.

person = {"name": "Alice", "age": 30}
person["age"] = 31

🧊 5. frozenset

  • ❌ Immutable
  • ❌ Unordered
  • ✅ Unique
  • ❌ Indexable
  • ❌ Duplicates not allowed

Use case: Hashtable version of set, usable as dict or set key.

fset = frozenset([1, 2, 3])
# fset.add(4)  # ❌ Error

📚 6. collections.deque

  • ✅ Mutable
  • ✅ Ordered
  • ❌ Not Unique
  • ✅ Indexable (partial)
  • ✅ Duplicates allowed

Use case: Fast appends/pops from both ends (queue/stack).

from collections import deque
dq = deque([1, 2, 3])
dq.appendleft(0)
dq.pop()

📊 7. collections.namedtuple

  • ❌ Immutable
  • ✅ Ordered
  • ❌ Unique not enforced
  • ✅ Indexable and attribute access

Use case: Tuple with named fields, lightweight class alternative.

from collections import namedtuple
Point = namedtuple("Point", "x y")
p = Point(10, 20)
print(p.x, p[1])

📐 8. collections.defaultdict

  • ✅ Mutable
  • ✅ Ordered (Python 3.7+)
  • ✅ Unique keys
  • ✅ Key-based access

Use case: Dict with default factory (no KeyError on missing keys).

from collections import defaultdict
d = defaultdict(int)
d["a"] += 1

🔁 9. collections.Counter

  • ✅ Mutable
  • ✅ Ordered (in output)
  • ✅ Unique keys
  • ✅ Key-based access

Use case: Count frequency of items (e.g., words, characters).

from collections import Counter
c = Counter("banana")
print(c["a"])  # 3

Exercises

NamedTuple

from typing import NamedTuple

class Point(NamedTuple):
    x: float
    y: float

p = Point(1.5, 2.5)
print(p.x, p.y)       # 1.5 2.5
print(p[0], p[1])     # 1.5 2.5
class Color(NamedTuple):
    red: int
    green: int
    blue: int

white = Color(255, 255, 255)
print(white.red)  # 255
class ApiResponse(NamedTuple):
    status_code: int
    message: str
    data: dict

res = ApiResponse(200, "OK", {"user": "kenan"})
print(res.status_code, res.data["user"])  # 200 kenan

Tuples

A tuple is a collection which is ordered and unchangeable or immutable.




Continue reading