Wednesday, May 3, 2023

Python Modules in Machine Learning

 1. Numpy

It is a module to work faster with numerical arrays. It is preinstalled for Anaconda(a python bundle).

import numpy as np


create ndarray

arr = np.array([1, 2, 3])     # from list

arr = np.array([[1, 2, 3], [4, 5, 6]])

arr = np.array((1, 3, 2))    #  from tuple

arr = np.arange(10)   #   using range

arr = np.arange(1,10,2)

arr = np.linspace(1, 19, 10)  # using linspace   # 19 included, 10 divisions

arr = np.zeros((3,2))

arr = np.random.rand(2,3)   # using random

np.array([1, 2, 3, 4], dtype='f'),    np.array([1, 2, 3, 4], ndmin=5)   


access

arr[1,2]

arr[:2, ::2]      #    first 2 rows and alternate columns(0 and 2)


ndarray operations

arr = np.array([[6,7,8,5],[4,6,7,1]])

print(arr.dtype) # int32

print(arr.ndim, arr.shape, arr.size)  # 2, (2,4), 8

print(arr+arr, arr-arr, arr*arr, arr>arr) # Element-wise operations

print(arr.T)  #   transpose

print(arr.sum(axis=0)) #   0 for column, 1 for row

print(arr.max(axis = 1)) # max in each row

print(arr.dot(arr.T))  # matrix multiplication

print(arr.reshape(2,2,2))  # to 3d

print(arr.flatten())   # to 1d

print(arr.astype('f'))

print(arr.copy())  # deep copy  # view() is for shallow copy, so changes are affected

print(arr[arr>6])    #  filter/subset


numpy operations

print(np.empty, np.zeros((3,2)), np.zeros_like(arr), np.ones((3,2)),np.identity(4), np.floor(arr))

print(np.dot(arr,arr.T))

print(np.add(arr,arr))

print(np.subtract(arr,arr))

print(np.multiply(arr,arr))

print(np.log(arr))

print(np.square(arr))

print(np.sqrt(arr))

print(np.sin(arr))

print(np.around(arr, 2))

for x in np.nditer(arr):   # to iterate through an n dimensional array

  print(x)

print(np.amin(arr))  # minimum

print(np.vstack((arr, arr)))  # added below  # 2 brackets

print(np.concatenate((arr,arr)))  # same as vstack

print(np.hsplit(arr, 2))  # split vertically

print(np.where(arr == 4))   # search index

print(np.sort(arr, axis = 0))

print(np.mean(arr,0), np.median(arr,0), np.percentile(arr,10))  # statistical functions

print(np.std(arr,axis=0)) # standard deviation 

print(np.var(arr)) # variance



2. Pandas

This module is commonly used for dataset management. It is preinstalled with Anaconda distribution. It has two data structures - series(1d) and dataframe(2d).

import pandas as pd


Create 

Series

lst = ['A', 'B', 'C', 'D', 'E']

ser = pd.Series(lst)            #  from list

ser = pd.Series(lst, index = ['i', 'j', 'k', 'l', 'm'])

dic = {1:'A', 2:'B', 3:'C', 4:'D', 5:'E'}      

ser = pd.Series(dic)     #  from dictionary (key becomes row index)

ser = np.array(['P','a','n','d','a','s'])    # from ndarray

Dataframe

A DataFrame has both row index and column index.

df = pd.DataFrame(lst, columns=['Alphabets'])    #   from list with column index

dic = {"calories": [420, 380, 390],

  "duration": [50, 40, 45] }

df = pd.DataFrame(dic, index = ["day1", "day2", "day3"])   #   from dictionary  #  value is list;   key is column index;     index is row index

df_tuple = [(1990, 'Italy','Germany', 115), (1994, 'USA', 'Brazil', 141)]

data = pd.DataFrame(df_tuple, columns=['Year','Country', 'Winner', 'Goals'])   #  from tuple  # 1 tuple element is one row.

df = pd.DataFrame({'Col1': pd.Series(lst1),'Col2': pd.Series(lst2)})   #  from Series

df = pd.read_csv('datasets/ted_data.csv')     #   from csv


Access

ser[0], ser['i':'k']     # using row location or row index

df[0:5], df['Country'], df[['Country', 'Year']]    # using row location or column index

df.loc[:, 'Country'],  df.loc['i:'j', 'Country':'Goals'] ,  df.loc[0:2, 'Country':'Goals']  # using row-column indices or row location-column index

df.iloc[:, 3], df.iloc[1,[2,3]]    #  using row-column locations.

df.at[0,'A'] is same as df.loc[0,'A']

Pandas Operations

pd.read_csv("file.csv")

pd.concat([df1, df2]),   pd.merge(df1,df2,on='city', how='left')

pd.get_dummies(pd.Series(list('abcaa')))     # creates a T/F table with columns a,b and c.

pd.isna(df)    #  creates a T/F  table for each cell

pd.to_datetime(df["Time"])

Series/Dataframe Operations

ser.value_counts(), ser.str

df.at[0,'A'] = 103    # setting

df['A'] = ser

df['class'].replace(['First','Second','Third'], value = [1,2,3], inplace=True)

df.dtypes, df.index, df.columns, df.T, len(df), df.to_csv("file.csv")

df.head(), df.tail(3), df.info(), df.describe(), df.mean(), df.mode(), df.median()

df.to_numpy(), df.copy(), df.dropna(how="all"), df.fillna(value=5)

df.sort_values(by="B", ascending=False), df[df['E']='e']

df.loc[df['usertype'] == 'Subscriber']          # where clause

df.groupby("A")[["C", "D"]].sum()         # group by and aggregate

df.drop('col_3', axis=1, inplace=True)     # drop column

df.apply(lambda x: x.max() - x.min())

df.plot(), df.unique(), df.nunique()  # each column , df.values.tolist(),   df.isnull().sum() 

for i,j in df.iterrows():      #   i is index, j is Series

    print(j['genre'])       #  j.index gives column name


3. Matplotlib

This is a graph plotting library.

import matplotlib.pyplot as plt

plt.plot([1,2,3,4,5],[1,4,9,16,25], color='r', linestyle='--', marker='>'#  line graph

plt.title("Simple Plot")

plt.ylabel("y-axis")

plt.xlabel("x-axis")

plt.legend()

plt.show() 

 

ypoints = np.array([3, 8, 1, 10])

plt.bar(['Blue', 'Grey', 'Yellow', 'White'], ypoints)    # bar graph   # barh for horizontal

# used when x values are categorical (supports numerical also)


plt.subplot(1, 2, 1)  # 1 row, 2 columns, 1st column

plt.scatter(x,y)   #    scatter/dot graph

plt.subplot(1, 2, 2)

plt.pie(y1)     # pie chart, used when there is no x


blood_sugar = [113,85,100,90,150,143,110,86,82]

plt.hist(blood_sugar,bins=[77,100,125,150])     # histogram,  used when x values are in ranges; y shows count


4. Seaborn

This library is built on top of Matlibplot. It uses Pandas datastructure.

import seaborn as sns

import matplotlib.pyplot as plt

df = sns.load_dataset('iris')

sns.lineplot(x="species", y="petal_length", data=df)

plt.title('Title using Matplotlib Function')  

plt.show()

sns.barplot(x="species", y="petal_length", data = df)

sns.scatterplot(x='species', y='petal_length', data=df)

sns.histplot(x='species', y='petal_length', data=df)

sns.catplot(x='species', y='petal_length', data=df)

sns.boxplot(x='species', y='petal_length', data=df)

sns.relplot(x='species', y='petal_length', data=df)

sns.displot(x='petal_length', data=df, kde=True)

sns.countplot(x='petal_length', data=df)

sns.heatmap(df.corr())

sns.pairplot(df)  # scatter + count


5. Scipy

This library is used for Scientific computations. It is built over Numpy.

from scipy.stats import binom

from scipy.stats import norm

from matplotlib import pyplot as plt

import numpy as np

# binomial distribution. 2 values eg: H, T

n,p = 2,.5  

x = np.array(range(0, n+1))

prob = np.array([binom.pmf(k, n, p) for k in x]) 

plt.xlabel('x')

plt.ylabel('Probability')

plt.bar(x, prob)

plt.show()

# normal distribution

n=50

x1 = np.array(range(0, n+2))

prob1 = np.array(norm.pdf(x1,np.mean(x1),np.std(x1))) 

plt.plot(x1, prob1)

plt.show()

x2 = np.array(range(0, n+2))

prob2 = np.array(norm.cdf(x2,np.mean(x2),np.std(x2))) # cumulative

plt.plot(x2, prob2)

plt.show()


6. statistics

statistics.mean(), statistics.median(), statistics.median_grouped(), statistics.mode(), statistics.pstdev(), statistics.stdev(), statistics.pvariance(), statistics.variance()

Monday, April 10, 2023

Small Programs using Python

 1. How to find the minimum value in a list?

Primitive

lst = [3, 6, 7, 2, 1, 5]

print(min(lst))

Object:

lst = [Car('Nano', 150), Car('Ferrari', 500), Car('Maruti', 250)]

new_lst = min(lst, key=lambda car: car.max_speed)



2. How to get a list sorted?

Primitive

lst = [3, 6, 7, 2, 1, 5]

sort(lst)

Object:

lst = [Car('Nano', 150), Car('Ferrari', 550), Car('Maruti', 250)]

new_lst = sorted(lst, key=lambda car: car.max_speed)

Reverse Order:

new_lst = sorted(lst, key=lambda car: car.max_speed, reverse=True)



3. How to reverse a String or a List?

List of Primitives

lst.reverse()

list(reversed(lst))

lst[::-1] 

String:

list(string).reverse()

string = "".join(reversed(string))

str[::-1]

List of Objects:

sort in reverse order.



4. How to search an element?

List of Primitives

lst = [3, 6, 7, 2, 1, 5]

print(6 in lst)

print(lst.index(6) > -1)

String

str = 'Eleven boys have a good football court.'

result = str.find('ball')

List of Objects:

lst = [Car('Nano', 150), Car('Ferrari', 500), Car('Maruti', 250)]

print(any(filter(lambda car: car.max_speed > 400, lst)))

# filter returns iterator, list(filter()) returns list

print(any(car for car in lst if car.max_speed > 400))



5. How to count the occurrences?

List of Primitives

lst = [3, 6, 7, 2, 1, 5]

print(lst.count(2))

String

str = 'Eleven boys have a good football court.'

print(str.count('o'))

List of Objects:

lst = [Car('Nano', 150), Car('Ferrari', 500), Car('Maruti', 250)]

print(len(filter(lambda car: car.max_speed > 400, lst)) )    

print(len([car for car in lst if car.max_speed > 400])) # square bracket same as list( ).



6. How to replace an element?

List of Primitives

lst = [3, 6, 7, 2, 1, 5]

lst[2] = 17

list(map(lambda x: x+10, lst))           

String

str = 'Eleven boys have a good football court.'

str = str.replace('boys', 'girls')

List of Objects:

lst = [Car('Nano', 150), Car('Ferrari', 500), Car('Maruti', 250)]

#   list of map of lamba cannot be used for changing object's state, it can only replace an object.

for car in lst:

    if car.max_speed > 450:

        car.max_speed = 450


Wednesday, April 5, 2023

Design Patterns in Python

1. Creational Design Patterns

Factory Method: The constructor stores a dictionary. A Factory method gets the state value from this dictionary passing the key as String.

Abstract Factory method: Here, the constructor should return objects of other classes based on whatever key is passed.

Singleton: A class variable is initialized by the constructor and a static getInstance() method returns that variable every time an object creation is initiated.

Prototype: This uses copy.copy(obj) or copy.deepcopy(obj) to create objects.

Builder: A builder class is used to work on different objects which are called one after the other.


2. Structural Design Patterns

Adapter: An actual object is passed to an adapter constructor to modify it for further operations.

Bridge: A composition (has-a relationship) is used where a class has another class as its instance variable initialized through constructor.

Composite: This ensures that a hierarchy is defined in a tree model by adding leaf classes to a list type instance variable of the composite class.

Decorator:  Each child class adds extra behaviour to parent as,

class FirstConcreteHandler(AbstractHandler):

class SecondConcreteHandler(AbstractHandler):

class ThirdConcreteHandler(AbstractHandler):

self.handler = FirstConcreteHandler(SecondConcreteHandler(ThirdConcreteHandler()))


3. Behavioural Design Patterns

Observer: This ensures that all Observer classes are updated when there is a change.A common class has instance variables of all Observer classes. It also has methods to update the Observers whenever its onchange() method is called.

Tuesday, April 4, 2023

Modules in Python

 A Module is a file containing functions, variables and classes. 

eg: Create a module named printNumbers.py as,

def printForward(n):

    for i in range(n):

        print(i+1)

def printBackwards(n):

    for i in range(n):

        print(n-i)


This can be imported to other files as,

import printNumbers as pn     #   module import

pn.printForward(5)

or,

from printNumbers import printForward      #    function import

printForward(5)


In order to view all the functions inside a module, use dir.

dir(printNumbers)


A module can be executed as a script if the below code is added,

if __name__ == "__main__":  

        printForward(5)



Built-in Functions

Python provides some built-in functions which can be used directly without importing.

eg: any(), print(), list(), input(), id(), len(), type(), iter(), sum().


Built-in Modules

Built-in modules can be used directly without installing. Some common built-in modules are,

1. math

This module is for mathematical operations. It has functions like ceil(), cos(), factorial(), prod(), isfinite(), sqrt(), pow(), isnan() and constants like nan, pi.

import math

print(math.sqrt(16))


2. os

This module performs many tasks of operating system. It has the functions mkdir(), chdir(), rmdir(), listdir() and getcwd().

import os

os.mkdir("d:\\tempdir")

os.chdir("d:\\temp")

os.getcwd()     #returns 'd:\\temp'


3. random

It has various methods to return a random number.

import random

random.random()    #   Returns a random float number between 0.0 to 1.0. 

random.randint(1,100)   #   Returns a random integer between the specified integers

random.randrange(1,10,2)   #  Returns a random element from the range created by start, stop and step.

random.choice([12,23,45,67,65,43])   #  Returns a randomly selected element from a sequence object such as string, list or tuple

numbers=[12,23,45,67,65,43]

random.shuffle(numbers)    #  This functions randomly reorders elements in a list.


4. statistics

This provides various statistical modules.

mean() to find arithmetic mean of numbers in a list.

median() to get the middle value.

mode() for most repeated.

stdev() for standard deviation.

import statistics

lst = [2,5,3,2,8,3,9,4,2,5,6]

print(statistics.mode(lst))

print(statistics.stdev(lst))


5. requests

This allows us to make HTTP requests.

import requests

url = 'https://www.w3schools.com/python/demopage.php'

x = requests.get(url)

myobj = {'somekey': 'somevalue'}

x = requests.post(url, json = myobj)


6. re

This module is for regex expressions. Most functions take in two parameters - pattern and text.

import re  

text = "The dog is barking. The dog is sleeping."  

result = re.search("dog", text)   # result.start() gives starting index

result = re.sub("dog", "cat", text)    # substitute

result = re.split("\s", text)   #  split at space

result = re.match("\S+@\S+\.\S+" , text)    #   email pattern, result.group(1) gives first match

In the pattern = "^[A-Za-z]{2}[0-9]+$", ^ stands for start, [ ] for characterset, { } for repeat, + for one or more and $ stands for end. Also, * is for 0 or more, ? for 0 or 1, (a|b) for either 'a' or 'b' and /d is for digit.


7. unittest

Testing can be done for a single statement as,

assert sum([ 2, 3, 5]) == 10, "Should be 10"  

But for multiple statements, we need the unittest module.

import unittest  

class TestingSum(unittest.TestCase):  

    def test_sum(self):  

        self.assertEqual(sum([2, 3, 5]), 10, "It should be 10")  

    def test_sum_tuple(self):  

        self.assertEqual(sum((1, 3, 5)), 10, "It should be 10")    

if __name__ == '__main__':  

    unittest.main()  


Other built-in modules are,

threading - adds multithreading capabilities to a class as,

class ClickTheMouse(threading.Thread): 

sys  - for managing Python runtime environment. eg:sys.path, sys.argv

collections  - provides alternatives to built-in containers. eg: namedtuple(), OrderedDict(), deque()

time  - time.ctime() gives the current time.

email  - for managing email messages

gc  - for garbage collector

html  - for manipulating html requests.

json  - to create json notations

pickle, marshal  - for serialization

locale  - to set locale

logging  - to add logs

sched  - for schedulers


Monday, April 3, 2023

Functional Programming in Python

 Functional programming is a programming paradigm that breaks down a problem into individual functions. In this paradigm, we avoid mutable data types and state changes as much as possible. It also emphasizes RECURSION rather than loops. map(), filter() and reduce() are the three cornerstone functions of functional programming.



map()

This first argument to map() is a transformation function, where each original item is transformed into a new one. 

num = [2, 3, 6, 9, 10]

def cube(num):

  return num ** 3

cubed = map(cube, num)

print(list(cubed))


Another way:

cubed = map(lambda n: n ** 3, num)

 

Another method:

list(map(lambda x, y: x / y, [6, 3, 5], [2, 4, 6]))

[3.0, 0.75, 0.8333333333333334]


A lot of math-related transformations can be performed with map().

For tuples we use starmap().


import itertools 

num = [(2, 3), (6, 9), (10,12)] 

multiply = itertools.starmap(lambda x,y: x * y, num)

list(multiply) #  [6, 54, 120]



filter()

A filtering operation processes an iterable and extracts the items that satisfy a given condition. The function argument must be a single-argument function. It’s typically a boolean-valued function that returns either True or False. The filter() accepts only one iterable.


num = [12, 37, 34, 26, 9, 250, 451, 3, 10]

even = list(filter(lambda x: (x % 2 == 0), num))

print(even)


sort() 


The sort method is a helpful tool to manipulate lists in Python. For example, if you need to sort a list in ascending or reverse order, you can use the following:


num = [24, 4, 13, 35, 28]

num.sort()

num.sort(reverse=True)

It is important to note that the sort() method mutates the original list and it is therefore impossible to revert back the list’s items to their original position. 



groupby()

ITERTOOLS.GROUPBY() takes a list of iterables and groups them based on a specified key. The key is useful to specify what action has to be taken to each individual iterable. The return value will be similar to a dictionary, as it is in the {key:value} form. Because of this, it is very important to sort the items with the same key as the one used for grouping. 


import itertools

spendings = [("January", 25), ("February", 47), ("March", 38), ("March", 54), ("April", 67),

             ("January", 56), ("February", 32), ("May", 78), ("January", 54), ("April", 45)]

spendings_dic = {}

func = lambda x: x[0]

for key, group in groupby(sorted(spendings, key=func), func):

    spendings_dic[key] = list(group)

print(spendings_dic)


{'April': [('April', 67), ('April', 45)],

 'February': [('February', 47), ('February', 32)],

 'January': [('January', 25), ('January', 56), ('January', 54)],

 'March': [('March', 38), ('March', 54)],

 'May': [('May', 78)]}

In the above snippet, we used sorted() instead of sort(). This is because we wanted to sort an iterable that was not a list.


Contrary to sort(), sorted() will create a copy of the original list, making it possible to retrieve the original order. 

Finally, we can use map() from the previous section to sum the monthly expenses:


monthly_spendings = {key: sum(map(lambda x: x[1], value)) for key, value in spendings_dic.items()}

print(monthly_spendings)

{'April': 112, 'February': 79, 'January': 135, 'March': 92, 'May': 78}



reduce()

The REDUCE() function implements a technique called FOLDING or reduction. It takes an existing function, applies it cumulatively to all the items in iterable, and returns a single final value.


reduce() was originally a built-in function and was moved to functools.reduce() in Python 3.0.


Unless you cannot find any solution other than reduce(), you should avoid using it. The reduce() function can create some abysmal performance issues because it calls functions multiple times, making your code slow and inefficient. Functions such as sum(), any(), all(), min(), max(), len(), math.prod() are faster, more readable, and Pythonic. 


from functools import reduce

yearly_spendings = reduce(lambda x, y:x + y, monthly_spendings.values())

print(yearly_spendings)

496


Serialization in Python

 There are different ways in Python to read data from files and to write data to files.


1. Using input from console

x = input('Enter your name:')

print('Hello, ' + x)



2. Using File Handling methods

The file handling methods in Python include open, close, readlines and writelines.

Common operation modes for files are r(read), w(write), a(append at end) and r+(read and write).


# read

text_file = open('/Users/pankaj/abc.txt','r')

line_list = text_file.readlines()

for line in line_list:

    print(line)

text_file.close()


# write

text_file = open('/Users/pankaj/file.txt','w')

word_list= []

for i in range (1, 5):

    print("Please enter data: ")

    line = input() 

    word_list.append(line) 

text_file.writelines(word_list) # overwrites file data

text_file.close() 


# append

text_file = open('/Users/pankaj/file.txt','a')

word_list= []

for i in range (1, 5):

    print("Please enter data: ")

    line = input() 

    word_list.append(line)

text_file.writelines(word_list)

text_file.close() 


The file.seek(7) moves the cursor to the specified location.



3. Serialization

Serialization is the process of converting the object into a format that can be stored or transmitted.  Python has a number of built-in modules for this process: marshall, json, and pickle. The marshall is mainly used by the interpreter. The json produces human-readable output and works well with other languages, but it works only with certain data types.So pickle provides the best Serialization solution. 

pickle.dump(): to convert data into serialized form

pickle.load(): to convert serialized format into original data type.


# pickle

import pickle

number_of_data = int(input('Enter the number of data : '))

data = []

for i in range(number_of_data):

    raw = input('Enter data '+str(i)+' : ')

    data.append(raw)

file = open('important', 'wb')

pickle.dump(data, file)

file.close()


# unpickle

file = open('important', 'rb')

data = pickle.load(file)

file.close()

for item in data:

    print(item)

Static in Python

Instance variables

They are declared inside a method or the constructor of a class. Their values vary from object to object.

Class variables

They are declared inside the class, but outside all method definitions. They are shared among all instances of a class. They are allocated memory when an object for the class is created for the first time. They can be accessed by either using objects or class name.

Instance methods

They are specific to each object. They can access both class variables and instance variables. They use self as the first parameter. They can be called only using the object of the class.

Class methods

They are shared among all objects of the class. They can access only class variables. They use cls as the first parameter. They can be called using ClassName or by using a class object. They are mostly used as factory methods.

Static methods 

They are also shared among all objects of the class. They cannot access any variable of a class. They do not take any extra parameter. They can be called using ClassName or by using a class object. They are mostly used as utility methods.

class Student:

    # class variables

    school_name = 'ABC School'


    # constructor

    def __init__(self, name, age):

        # instance variables

        self.name = name

        self.age = age


    # instance method

    def show(self):

        print(self.name, self.age, Student.school_name)


    @classmethod

    def change_School(cls, name):

        cls.school_name = name


    @staticmethod

    def find_notes(subject_name):

        return ['chapter 1', 'chapter 2', 'chapter 3']

Static methods are useful in creating Utility functions.


Decorator

A decorator is a function that takes another function as an argument and extends its behavior without explicitly modifying it. eg: for logging, debugging, authentication, measuring execution time, and many more. 

def decorator(func):

  def wrapper():

    print("This is printed before the function is called")

    func()

    print("This is printed after the function is called")  

  return wrapper

This decorator function is called by adding @decorator above the actual function. eg: @staticmethod, @classmethod, @property (for getter/setter). Its main function is to support code reusability.


Iterator

It is a way of iterating over iterable objects like lists, tuples, dicts, and sets.

tup = ("apple", "banana", "cherry")

itr = iter(tup)

print(next(itr))

print(next(itr))

print(next(itr))


Generator

Generators are functions used to create iterators. These functions use one or more yield statements instead of return.

def seq(x):

    for i in range(x):

        yield i      

range_ = seq(4)

print(next(range_))

print(next(range_))

print(next(range_))

print(next(range_))

Generator functions are more memory efficient than normal functions.

Multithreading in Python

Multithreading makes threads appear to be running parallelly. We can do multithreading in Python using the threading module.


import threading

def even():

    for i in range(0,20,2):

        print(i)

def odd():

    for i in range(1,20,2):

        print(i)

if __name__ == "__main__":      # main method

    trd1 = threading.Thread(target=even)

    trd2 = threading.Thread(target=odd)

    trd1.start() 

    trd2.start() 

    trd1.join()   # waiting until thread 1 is done

    trd2.join()   # waiting until thread 2 is done

    print('End')


functions:

threading.active_count(), threading.main_thread(),  threading.current_thread().name 

threading.enumerate()    # list of active threads


Synchronization

A race condition occurs when two or more threads access shared data and try to change it at the same time. We use the locks to solve this problem. The locks provide two methods: acquire, release.

lock = threading.Lock() 

trd1 = threading.Thread(target=increment,args=(lock,))

def increment(lock):

    for _ in range(200000):

        lock.acquire()

        a += 1

        lock.release()

Containers in Python

Container is any object that can hold other objects. There are 4 built in containers:

1. List

A list is defined as an ordered, mutable, and heterogeneous collection of objects.

list1=[1,'a',5.6,'Python']   # create

list1[1],  list1[-4:7]    # read

list1[1]=1.2    # reassigning

for i in lst:     #  loop using in

print(i)

for i in range(len(lst)):     # loop on index

  print(lst[i])

new_list=[expression for element in list]   # list comprehension

eg: string="Python"

list3=[i for i in string]         # create

print(list3)    #  gives ['P','y','t','h','o','n']


list1=[1,2,3,4,5,6]

list2=[ i if i%3==0 else -1 for i in list1 ]          # list comprehension with if else (if no else, if part is at the end)

print(list2)


list1.append(17)   # add at end

list1.extend([2,8.0,'l'])   # add >1

list1.insert(2,'a')    #  add at 2nd index



del list1[1:4] #  deleting 2nd to 4th elements

lst.pop()  # delete last element

lst.pop(1)  # delete 1st index element

lst.remove('x')  # delete element's first occurrence


len(lst), min(lst), sum(lst)

list('abc')   # type casting

any(lst),  all(lst)


lst.index('s')   # find     (in can also be used to find)

lst.count('x')     # find

lst.reverse()     # reverses, no sorting

lst.clear()


m_list=[[1,2,3,4],['a','b','c'],[4.5,6.7,1.3]]     #2d list

print(list1+list2)     #   Concatenation

print(list2*3)   # repeats thrice

print('b' not in list2)    #  boolean

lst.copy(),   list(lst)      # copy

lst = [ ]  # empty list

Sort

lst.sort()    #   sorts the list    , available only in list

sorted(lst)    # returns sorted list, original unaffected, method in other containers also

def check(item1, item2):    # comparator method

    return lst(item1) - lst(item2)

from functools import cmp_to_key

sorted(mylist, key=cmp_to_key(check))



2. Tuple

Tuples are ordered and heterogenous, but they are immutable.

tup = ("python", 1.1, 3)      # create

tup = tuple(lst) ,   tup = tuple(str),   tup = (3,)   # create

tup[0], tup[-4:-1]  # access

a, b, c = tup  #  unpacking

Addition to a tuple can be done in 2 ways - by concatenation, or by converting to list and append.

Tuple3 = Tuple1 + Tuple2    #   concatenation. 

No update or reassign can be done on tuple since immutable.

del tup  # delete

tup.index(), tup.count()    # methods to find

len(tup), any(tup), all(tup), max(tup), sorted(tup)   #   functions on tuple  # sorted returns list

Methods that cannot be used for tuples:   append(), insert(), remove(), pop(), clear(), sort(), reverse()

for i in tup:    # loop

tup1=(1,2,3), tup2=(1,2,3), tup1 is tup2    # returns false

tup = ( )   # empty tuple



3. Set

Sets are unique, unordered, heterogenous and mutable. But a set cannot have mutable elements like lists, sets, or dictionaries (Strings and tuples are immutable along with all primitives)

Set = {'A', 'B', 'C', 'D'}     #   create

Set = set(lst), Set = set(tup)    # create

for x in Set:      # loop

We cannot read from set using index.

Set.add('E')     # insert

Set.update(set1)    #   concatenate

Set.update(lst)

set2 = Set.union(set1)  # concatenate with assignment

Set.remove('D')     # delete

Set.discard('D')

Set.pop()    # cannot give index

Set.clear()

del Set


len(Set), all(Set), any(Set), sorted(Set)     # built-in functions

max(Set), sum(Set) for homogeneous 

set2 = Set.intersection(set1)    # common elements

Set.isdisjoint(set1)     # True if no common elements

set2 = Set.difference(set1)     # minus

set2 = Set.symmetric_difference(set1)   # exclude common

set1.issubset(Set) 

set1 = Set.copy()

Cannot use Set={ } for empty set since that becomes a dictionary.

set1={'abab'} gives {'abab'}

set2=set('abab') gives {‘b’, ‘a’}



4. Dictionary

They store values in key-value pairs.  They are ordered (from Python 3.7) with unique keys. They are mutable. But their keys should be immutable.

dic = {'a':1,'b':2,'c':3}   #   create

dic = dict(a = "John", b = 36, c = "Norway")    #      create with equal to and no quotes for keys

dict[lst]    

dic['a'], dic.get('a')      #    access

dic = { }   #  empty dictionary

dic.keys()  ,   dic.values()

dic['a'] = 5      #    add ,  reassign ,   update

dic.pop('a') ,  del dic,  dic.clear() , dic.popitem()    #   delete

for i in  dic:      # loop keys

for x, y in dic.items():

dic.copy(),  dict(dic)    #  copy

Nested dictionary has dictionary as value, accessed as  dict['a']['age']

len(dic), any(dic),  all(dic), sorted(dic)

dic.fromkeys({0,1,2,3,4})    # create None valued dictionary with keys

dic.has_key('a')

dic={x:x*2 for x in ['a','b','c','d','e']}   #    dictionary comprehension

dic = {1: 'Geeks', 2: 'For',

        3: {'A': 'Welcome', 'B': 'To', 'C': 'Geeks'}}     # nested dictionary


Strings in Python

String is an immutable data structure in Java. That means, once value has been assigned to a String, it can’t be changed and if changed, a new object is created. It is also a sequence of characters. Python does not have a character data type, a single character is simply a string with a length of 1. 

Create

String str = "Test"

String str = 'Test'

String str = '''Tes

t'''

Retrieve

String characters can be retrieved with the index.

s = str[3] # fourth character

s = str[-2] # second last character

s = str[1:3] # slicing, returns characters from 1 to 2

i = str.index('e') # returns index

str.index('e', 2, 7) # start and stop locations

str.rindex('e')  # last index


Add/Update/Delete

str = "Hello".join(str)  # using join

str = "Hello" + str[0] + 'eeeee' + str[1:]  #  using plus  # indexing and slicing

str += "hi" 

str = str.replace('l','m')

str = str[0:4]   # deletion

del str

str[0] = 'x' will give error


In all the three cases, the result has to be reassigned to the value, else value will return unchanged.


Formatting

str = r"The \n stands for next line"    #  raw string

str = "{} {} {}".format('I', 'like', 'mango')

str = "{0} {2} {1}".format('I', 'mango', 'like')

var="mango"

str = f"I like {var}"

num = 12.3456789

print('Two decimals: %3.2f' %num)

print('Four decimals: %3.4f' %num)

print(a,b)  # concat

str1 = ' '

str2 = 'geeks'

print(repr(str1 and str2))  # returns ' '   # repr is printable representation to print quotes

print('a' and 'b')  # returns b or second element for and

print('a' or 'b')  # returns a or first element for or

'a' * 3 # returns aaa


Operations

Other operations we can do with a String are,

len(str),  str.upper(), str.strip() 

str.split(',')   # returns list

't' in str, str.find("t"),   str.index("t")

str[2:10:2]   # start,stop,step

str[::-1]   # to reverse

print(type(str)) is String

for x in "banana":

  print(x)


str(obj)  # type casting

ord(str) to get ascii

chr(str) to get back string from ascii

str[len(str)-1]

str.isalnum()   # alphanumeric


Comment inside a method given at the top with triple quotes is called DocStrings.


Memory

str="check" and str1="check" are saved in the same memory location.

str==str1 checks for value and returns true.

str.__eq__(str1) also checks for value and returns true.

__eq__() method can be overridden in a class.

str is str1 checks for memory location and returns true


(In Java, == checks for location and .equals() of String is overridden to check for value. Location is same within Stringpool.)


Now, str="check@" and str1="check@" are saved in different memory locations due to special character.

So str==str1 is true, str.__eq__(str1) is true, but str is str1 is false.

String objects are saved in the heap just like any other object. But String interning is a process that reuses basic alphanumeric Strings. This saves a lot of memory.

OOP concepts in Python

Python is an Object Oriented Programming Language. In Python, everything is object, but everything is not in classes. The Basic OOP concepts are,

Abstraction

Python has to import Abstract Base Class to add the feature of abstraction.

from abc import ABC,abstractmethod

class Polygon(ABC):

   @abstractmethod    

   def sides(self):   

      pass  

  

class Triangle(Polygon):  # Polygon is parent

   def sides(self):   # all methods should pass self

      print("Triangle has 3 sides")   

class Square(Polygon):   

   def sides(self):   

      print("Square has 4 sides")       


Triangle().sides()   # Class() creates object

Square().sides()   # function call is outside any class


Polymorphism

Two ways of achieving this are,

1. Overloading

def add(p, q, r = 0):  # default value given to make parameter optional
    return p + q + r  
print (add(6, 23))  
print (add(22, 31, 544))  

2. Overriding

class Bird:  
    def intro(self):  
        print("There are multiple types of birds in the world.")  
    def flight(self):  
        print("Many of these birds can fly but some cannot.")  
  
class Sparrow(Birds):  
    def flight(self):  
        print("Sparrows are the birds which can fly.")  
      
class Ostrich(Birds):  
    def flight(self):  
        print("Ostriches are the birds which cannot fly.")  
      
Bird().intro()
Sparrow().intro()  # same as bird
Ostrich().flight()   # overridden method


Inheritance

A child class extends the parent and overrides its necessary methods. 

class Vehicle:
    def drive(self):
print("Parent")

class Car(Vehicle):   # single inheritance
    def __init__(self):  # constructor
       Vehicle.__init__(self)  # calling parent constructor
    def drive(self):
print("Child")

class Nano(Car,Bus):  # multiple inheritance
    def drive(self):
print("Grand Child")

print(issubclass(Car,Vehicle))  # returns True
n = Nano()  
print(isinstance(n,Nano))   # returns True

Every class inherits from the base class called Object.



Encapsulation

In Python, instance variables are declared inside the constructor. They can be of 3 types 

class Employee:
    def __init__(self, name, project, salary):
        self.name = name   # public- accessible everywhere
        self._project = project   # protected with single underscore- accessible within class and subclasses
        self.__salary = salary   # private with double underscore- accessible only within class

Private members can be accessed using public getter methods or by name mangling. Getters and Setters are declared only for private variables, others can be accessed with dot.

def get_salary(self):
    print('Salary:', self.__salary)
print('Salary:', new Employee()._Employee__salary) # one underscore before and two after
print('Project:', new Employee()._project)

Saturday, March 25, 2023

Small Programs using Java

1. How to find the minimum value in a list?

Primitive

List<Integer> lst = Arrays.asList(1, 2, 3, 4, 56, 7, 89, 10);

System.out.println(Collections.min(lst));

Object:

List<Employee> lst = new ArrayList<Employee>();

lst.add(new Employee(10, "Raghu", 25000));

lst.add(new Employee(120, "Krish", 45000));

lst.add(new Employee(210, "John", 14000));

Employee minSal = Collections.min(lst, new EmpComp());

System.out.println(minSal);

 

class EmpComp implements Comparator<Employee>{ 

    public int compare(Employee e1, Employee e2) {

        return e1.getSalary().compareTo(e2.getSalary());

    }

}

Stream

lst.stream.min((e1, e2) -> e1.getSalary().compareTo(e2.getSalary())).get();


2. How to get a list sorted?

Primitive

Collections.sort(lst));

Object:

Collections.sort(lst, new EmpComp());

Stream:

lst.stream.sorted((e1, e2) -> e1.getSalary().compareTo(e2.getSalary())).collect(Collectors.toList()); 

Reverse Order:

Collections.sort(lst, Collections.reverseOrder());  

lst.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());


3. How to reverse a String?

Char Array:

Scanner scanner = new Scanner(System.in);

String str = scanner.nextLine();

char[] arr = str.toCharArray();

for (int i = arr.length - 1; i >= 0; i--)

System.out.print(arr[i]);

StringBuilder:

StringBuilder sb = new StringBuilder(str);

sb.reverse().toString();

Arraylist:

List<Character> lst = new ArrayList<>();

for (char c : str)

    lst.add(c);

Collections.reverse(lst);

Stream:

Stream.of(str)

      .map(word->new StringBuilder(word).reverse().toString())

      .collect(Collectors.joining(" ")).get(0);

Stream with index:

char[] arr = str.toCharArray();

IntStream.range(0, arr.length)

        .mapToObj(i -> arr[(arr.length - 1) - i])

        .forEach(System.out::print);

A String is a palindrome if the String is same as the Reversed String.


4. How to search an element?

In String:

if(str.indexOf("word") > -1)

In Arraylist of Primitives:

boolean found = lst.contains(2);

In Arraylist of Objects:

for (Employee emp : emplist) {

    if (emp.getName().equals(name)) {

        return emp;

    }

}

Using Stream:

Employee empl = emplist.stream()

  .filter(emp -> name.equals(emp.getName()))

  .findAny()

  .orElse(null);



5. How to count the occurrences? 

String:

Linear search:

for (int i=0; i<str.length(); i++){

    if (s.charAt(i) == c)

        count++;

    }

return count;

Binary Search:

while (low <= high) {

        mid = (low + high) / 2;

        if (a[mid].compareTo(x) < 0) {

            low = mid + 1;

        } else if (a[mid].compareTo(x) > 0) {

            high = mid - 1;

        } else {

            return mid;

        }

    }

Arraylist:

Collections.frequency(list, new Employee(321222, "John", 29)); 

public boolean equals(Employee e) {

    if(this.id.equals(e.getId()) && this.name.equals(e.getName())) {

        return true;

    }

    return false;

}

Stream:

lst.stream().filter(str -> str.indexOf("ch") > -1).count();

To get count of each item,

lst.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));



6. How to replace an element?

String:

str.replace('h', 'm');

Arraylist

Collections.replaceAll(lst, null, " ");

Stream:

List<String> newList = lst.stream()

                .map(s -> s != null ? s : "")

                .collect(Collectors.toList());


Friday, March 24, 2023

Design Patterns in Java

 Design Patterns provide an industry-standard approach to solving a recurring problem.


1. Creational Design Patterns

They define the way an object is created.

Factory Method: This ensures that the correct object is created according to a parameter received.

 Implementation: A Factory class is created which returns different Child objects based on an input String passed to its method/constructor and using a switch case. 

Eg:  A car company gets the request to create a car. This request is given to the factory which decides how the car should be created based on its model.

Abstract Factory method: This ensures that the correct object is created according to a parameter when there are multiple levels of subclasses.

Implementation: When there are two levels of overriding, an abstract factory class or an interface is used to identify the first level of child class and for identifying the second level, there are separate concrete factory classes. 

Eg: When a car factory handles different companies, it should first decide for which company and then decide which model to be manufactured.

Singleton: This ensures that only one object for a class is created. 

Implementation: A private constructor is created and a public synchronized static getInstance() method to call it. 

Eg: In an apartment, the residents decide that only one borewell should be dug for the entire community. 

Prototype: This ensures that a copy of the existing object is returned when a new object is requested. This is used when an object creation is costly due to some reason (like db calls).

Implementation: A Prototype class is created which implements Cloneable and defines clone method (shallow or deep). This also has a list of predefined objects. So getInstance() method simply clones the predefined objects when called.

Eg: A Xerox machine just takes multiple copies of the same content.

Builder: This ensures that an object is created step by step.

Implementation: Instead of the actual class using its setter methods, a builder class is populated with its setters step by step. Finally this builder object is passed as a parameter to the actual class' constructor to create the actual object. 

Eg: An excel/pdf report is generated after formatting it line by line.


2. Structural Design Patterns

They define the way different types of objects can have a connection.

Adapter: This ensures that a class gets some of the features from another class.

Implementation: If a class cannot use features from another class directly due to its hierarchy, another adapter class is created as a child of both the classes (implements interface of our class, extends other class) and this class' object is created for processing.

Eg: A phone charger has an adapter that converts AC to DC since phone cannot use AC directly from the socket.

Bridge: This ensures that two classes are loosely coupled.

Implementation: Since inheritance creates tight coupling, composition (has-a relationship) is used. A class has another class as its instance variable and methods to operate on that class. This helps in doing operations on both classes without affecting their hierarchies.

Eg: A switch can be used in a house to operate a fan without knowing the technical details of the fan. So switch acts as the bridge here.

Composite: This ensures that a hierarchy is defined in a tree model.

Implementation: An interface can have its implementations which in turn can have multiple child classes.

Eg: Employee hierarchy in a company. Each manager can have employees under him and managers are in turn coming under General Managers or Vice Presidents.

Decorator:  This ensures that the behaviour of all sub classes can get altered without actually modifying them.

Implementation: An interface has some subclasses. Another abstract class implements this interface and adds the extra behaviour. The abstract class has a constructor parameterized with an interface object. This way the extra behaviour can be added to the interface.

Eg: Pizza and its sizes come under one hierarchy. Decorations on the Pizza can be decided from a separate Decorator class.

Facade: This ensures that multiple classes can be accessed from only one central class without knowing their internal details.

Implementation: One Facade class has instance variables of multiple classes and a constructor in which other classes are instantiated.

Example: In a restaurant only the menu card is displayed to the customers hiding the background details.

Flyweight: This ensures that a lot of objects can be created without much memory requirement.

Implementation: This combines factory and prototype design patterns. A factory has a hashmap to save objects. When a new object request comes with its type passed as String, if the key (ie, type) is already present in the hashmap, it returns that object, else it creates new object using a switch case. Flyweight resources are immutable.

Example: String pool which reuses String literals.

Proxy: This ensures that an actual class is accessed only through its proxy.

Implementation: A Proxy class is created whose constructor actually creates objects for the Real class.

Example: UPI is a proxy for a Bank account.


2. Behavioural Design Patterns

They define the way objects talk to each other.

Chain of responsibility: This ensures that different classes are called one after the other. 

Implementation: Either we can call the classes in the order, or we can create objects inside constructor in the order.

Example: Supply chain of products

Iterator: This ensures that objects can be iterated through.

Implementation: An Iterator Class implements Iterator and overrides its next()/hasNext() methods. The actual class has iterator() method to create the object of the Iterator class, using which it can traverse through the lists in the Actual class.

Example: A video playlist

Mediator: This ensures that objects talk to each other only through the Mediator.

Implementation: A Mediator class has instance variables of other classes. The Mediator object is used to work on the other classes

Example: Travel Agencies work as Mediator for different air services.

Observer: This ensures that all Observers are updated when there is a change.

Implementation: A common class has instance variables of all Observer classes. It also has methods to update the Observers whenever its onchange() method is called.

Example: All travelers should be informed when there is a change in schedule.

Strategy: This ensures that different child objects can have different behaviours.

Implementation: An interface can add a behaviour to a particular class. But if it needs its implementation also, then that interface's concrete child is added as instance variable to the required child classes.

Example: An IT team may be looking for the skills Java, .Net etc. from the resources while all resources are part of the Employee hierarchy.




Wednesday, March 22, 2023

Functional Interface in Java

 Any interface with a SAM(Single Abstract Method) is a functional interface. It can have other static or default methods. 

public interface Testable {

    void printName(String name);

}

There are five ways of implementing this Single Abstract Method:

1. Using normal function inside the implementation class

class Child implements Testable{

    void printName(String name) {

        System.out.println("Hi " + name);

    }

}   

new Child().printName("Tester");

2. Using anonymous class to override

Anonymous class can extend or implement only one class/interface.

class Test {

    Testable obj = new Testable() {           

        void printName(String name) {

            System.out.println("Hi " + name);

        }

    };

    obj.printName("Tester");  // Parent object

 

3. Using lambda operator

class Test {

    Testable obj = (name) -> {System.out.println("Hi " + name)

// method name skipped since only one method

    obj.printName("Tester"); 

}   

4. Using method reference

Method reference can be used if lambda just calls one method.

class Test {

    Testable obj = System.out::println // Cannot print Hi // Skipping arguments

    obj.printName("Tester"); 

}

Method reference is of 3 types:

For calling Child's static method,

Testable obj = Child::print;      obj.printName("Tester"); 

For calling Child's non-static method,

Testable obj = new Child()::print;      obj.printName("Tester"); 

For calling Child's constructor,

Testable obj = Child::new;      obj.printName("Tester"); 


5. Using Built-in Functional Interfaces

Built-in Function interfaces are needed if the argument passed and the value returned are different, or if more than one argument needs to be passed.

Function

Function<Student,String> f = s->"Name:"+s.name +" and Age:"+s.age;

String str = f.apply(student) //Student object passed, String returned

BiFunction

BiFunction<Integer, Integer, Integer> bf = Arithmetic::add;  

int result = bf.apply(10, 20);  // Two integers passed, one Integer returned

Consumer

Consumer<String> c = System.out::println;

c.apply("Test"); // String passed, nothing returned.

There are also other variants of the Consumer — DoubleConsumer, IntConsumer, and LongConsumer. 

BiConsumer

Consumer<String,Integer> c = (name,age)->System.out.println("Name is "+name+" Age is "+age);

c.apply("Joe",12); // String and Integer passed, nothing returned.

Predicate

Predicate<String> p = (value) -> value != null;

p.apply("Test"); // String passed, boolean returned.

There are also other variants of the Predicate — DoublePredicate, IntPredicate, and LongPredicate. 

BiPredicate

BiPredicate<Integer,Integer> bp = (age,min)->age>=min;

bp.apply(22,18); // Two Integers passed, boolean returned.

Supplier

Supplier<String> s = ()->System.out.println("Hi");

s.apply("Test"); // Nothing passed, String returned.

There are also other variants of the Supplier — DoubleSupplier, IntSupplier, and LongSupplier. 


Other Built-in Java Functional Interfaces

Runnable –> This interface only contains the run() method.

Comparable –> This interface only contains the compareTo() method which can be overridden as 

Comparator<Book> byAuthor = (b1, b2) -> b1.getAuthor().compareTo(b2.getAuthor());

ActionListener –> This interface only contains the actionPerformed() method.

Callable -> This interface only contains the call() method.

Tuesday, March 21, 2023

Streams in Java

Streams are wrappers around a data source (Collection, array etc.) allowing us to operate on that data source. A stream does not store data and is not a data structure. It also never modifies the underlying data source.

Any operation involving Streams should have three sections - a source, one or more intermediate operations and a terminal operation

 

Source

1. An empty Stream is created as, 

Stream<String> stream = Stream.empty();

2. Any Collection object can be converted to stream using stream() method. 

List<String> lst = Arrays.asList("A", "B", "C", "D");

Stream<String> stream = lst.stream();

Set<String> set = new HashSet<>(list);

Stream<String> strem = set.stream();

3. A Stream can be created from an array in two ways as,

Stream<String> strm = Stream.of("a", "b", "c");

String[] arr = new String[] { "a", "b", "c" };

Stream<String> stream = Arrays.stream(arr);

4. By adding elements individually using the mutable Builder.

Stream.Builder<String> builder = Stream.builder();

Stream<String> stream = builder.add("a").add("b").add("c").build();

5. Create an infinite Stream using Stream.generate() method.

Stream<Double> stream = Stream.generate(Math::random).limit(4);

6. Create an infinite Stream using Stream.iterate()

Stream<Integer> IntegerStream = Stream.iterate(0, n -> n + 1).limit(10);

7. A File can be converted to stream as,

Stream<String> stream = Files.lines(filepath);

8. Using Primitive Streams

IntStream intStream = IntStream.range(1, 3); //1 2

LongStream longStream = LongStream.rangeClosed(1, 3); //1 2 3

9. Stream from a pattern match

Stream<String> stream = Pattern.compile("\\s").splitAsStream("A String");

 

Intermediate Operations

The Streams are further processed by zero or more intermediate methods combined together (pipelined). But actual processing doesn’t start till a terminal operation is invoked. This is called lazy evaluation.

1. filter() to exclude unwanted streams with a condition (known as Predicate)

stream.filter((Employee e)-> e.getAge() > 24)

2. sorted() to arrange in order. A comparator can be passed as parameter.

stream.sorted()

3. distinct() to get non-duplicate elements

stream.distinct()

4. map() to transform the stream using a Function.

stream.map(String::toUpperCase)

5. limit() to restrict the result count

stream.limit(5)

6. peek() to debug every intermediate operation

stream.filter(e -> e.length() > 3).peek(e -> System.out.println("Filtered value: " + e))

 

Terminal Operations

They give the final result. They don't return a stream.

toArray() : to get an array from the stream.

collect() : to convert stream into a Collection. eg: stream.collect(Collectors.toList())

count() : to get the count

reduce() : to get a single result from a sequence. eg: stream().reduce("", String::concat)

forEach() : to do something for each element. eg: stream.forEach(System.out::println)

min() : to get the minimum value based on comparator. Returns an Optional element. 

        eg: Optional<Address> mini = stream.min((i, j) -> i.compareTo(j))

              Address addy = mini.get();

              mini.ispresent(); // False if Optional is empty

max() : to get the maximum value based on comparator. Returns an Optional element.

anyMatch() : True if any element matches, else false. eg: stream.anyMatch(p -> p.getAge() < 20)

allMatch() : True if all elements matche, else false. eg: stream.allMatch(p -> p.getAge() < 20)

noneMatch() : True if no element matches, else false. eg: stream.noneMatch(p -> p.getAge() < 20)

findAny() : Returns Optional with any element.

findFirst() : Returns Optional with the first in order element.

 

Parallel Stream

Parallel Streams are executed parallelly. 

eg: List<Integer> lst = Arrays.asList(1, 2, 3, 4);

int sum = lst.parallelStream().reduce(5, Integer::sum);

Here the result is calculated as (5+1) + (5+2) + (5+3) + (5+4) where as in sequential it would have been 1+2+3+4+15. 

Another way of creating prarallel stream is, stream.parallel().forEach(System.out::println);